Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
lxc
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
lxc
Commits
db62570f
Unverified
Commit
db62570f
authored
Mar 28, 2021
by
Stéphane Graber
Committed by
GitHub
Mar 28, 2021
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3743 from brauner/2021-03-27/fixes_3
oss-fuzz: fixes
parents
d734e611
4c5479d2
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
208 additions
and
16 deletions
+208
-16
compiler.h
src/lxc/compiler.h
+193
-3
confile.c
src/lxc/confile.c
+9
-4
string_utils.c
src/lxc/string_utils.c
+4
-7
string_utils.h
src/lxc/string_utils.h
+1
-1
lxc-test-utils.c
src/tests/lxc-test-utils.c
+1
-1
No files found.
src/lxc/compiler.h
View file @
db62570f
...
@@ -7,6 +7,9 @@
...
@@ -7,6 +7,9 @@
#define _GNU_SOURCE 1
#define _GNU_SOURCE 1
#endif
#endif
#include <stdbool.h>
#include <linux/types.h>
#include "config.h"
#include "config.h"
#ifndef thread_local
#ifndef thread_local
...
@@ -25,6 +28,196 @@
...
@@ -25,6 +28,196 @@
#define __fallthrough
/* fall through */
#define __fallthrough
/* fall through */
#endif
#endif
#if defined(__GNUC__) && !defined(__clang__)
#if GCC_VERSION >= 50100
#define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
#endif
#endif
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define __must_check __attribute__((__warn_unused_result__))
static
inline
bool
__must_check
__must_check_overflow
(
bool
overflow
)
{
return
unlikely
(
overflow
);
}
#define is_signed_type(type) (((type)(-1)) < (type)1)
#define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type)))
#define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T)))
#define type_min(T) ((T)((T)-type_max(T)-(T)1))
/*
* Avoids triggering -Wtype-limits compilation warning,
* while using unsigned data types to check a < 0.
*/
#define is_non_negative(a) ((a) > 0 || (a) == 0)
#define is_negative(a) (!(is_non_negative(a)))
#ifdef COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW
/*
* For simplicity and code hygiene, the fallback code below insists on
* a, b and *d having the same type (similar to the min() and max()
* macros), whereas gcc's type-generic overflow checkers accept
* different types. Hence we don't just make check_add_overflow an
* alias for __builtin_add_overflow, but add type checks similar to
* below.
*/
#define check_add_overflow(a, b, d) __must_check_overflow(({ \
typeof(a) __a = (a); \
typeof(b) __b = (b); \
typeof(d) __d = (d); \
(void) (&__a == &__b); \
(void) (&__a == __d); \
__builtin_add_overflow(__a, __b, __d); \
}))
#define check_sub_overflow(a, b, d) __must_check_overflow(({ \
typeof(a) __a = (a); \
typeof(b) __b = (b); \
typeof(d) __d = (d); \
(void) (&__a == &__b); \
(void) (&__a == __d); \
__builtin_sub_overflow(__a, __b, __d); \
}))
#define check_mul_overflow(a, b, d) __must_check_overflow(({ \
typeof(a) __a = (a); \
typeof(b) __b = (b); \
typeof(d) __d = (d); \
(void) (&__a == &__b); \
(void) (&__a == __d); \
__builtin_mul_overflow(__a, __b, __d); \
}))
#else
/* !COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW */
/* Checking for unsigned overflow is relatively easy without causing UB. */
#define __unsigned_add_overflow(a, b, d) ({ \
typeof(a) __a = (a); \
typeof(b) __b = (b); \
typeof(d) __d = (d); \
(void) (&__a == &__b); \
(void) (&__a == __d); \
*__d = __a + __b; \
*__d < __a; \
})
#define __unsigned_sub_overflow(a, b, d) ({ \
typeof(a) __a = (a); \
typeof(b) __b = (b); \
typeof(d) __d = (d); \
(void) (&__a == &__b); \
(void) (&__a == __d); \
*__d = __a - __b; \
__a < __b; \
})
/*
* If one of a or b is a compile-time constant, this avoids a division.
*/
#define __unsigned_mul_overflow(a, b, d) ({ \
typeof(a) __a = (a); \
typeof(b) __b = (b); \
typeof(d) __d = (d); \
(void) (&__a == &__b); \
(void) (&__a == __d); \
*__d = __a * __b; \
__builtin_constant_p(__b) ? \
__b > 0 && __a > type_max(typeof(__a)) / __b : \
__a > 0 && __b > type_max(typeof(__b)) / __a; \
})
/*
* For signed types, detecting overflow is much harder, especially if
* we want to avoid UB. But the interface of these macros is such that
* we must provide a result in *d, and in fact we must produce the
* result promised by gcc's builtins, which is simply the possibly
* wrapped-around value. Fortunately, we can just formally do the
* operations in the widest relevant unsigned type (u64) and then
* truncate the result - gcc is smart enough to generate the same code
* with and without the (u64) casts.
*/
/*
* Adding two signed integers can overflow only if they have the same
* sign, and overflow has happened iff the result has the opposite
* sign.
*/
#define __signed_add_overflow(a, b, d) ({ \
typeof(a) __a = (a); \
typeof(b) __b = (b); \
typeof(d) __d = (d); \
(void) (&__a == &__b); \
(void) (&__a == __d); \
*__d = (__u64)__a + (__u64)__b; \
(((~(__a ^ __b)) & (*__d ^ __a)) \
& type_min(typeof(__a))) != 0; \
})
/*
* Subtraction is similar, except that overflow can now happen only
* when the signs are opposite. In this case, overflow has happened if
* the result has the opposite sign of a.
*/
#define __signed_sub_overflow(a, b, d) ({ \
typeof(a) __a = (a); \
typeof(b) __b = (b); \
typeof(d) __d = (d); \
(void) (&__a == &__b); \
(void) (&__a == __d); \
*__d = (__u64)__a - (__u64)__b; \
((((__a ^ __b)) & (*__d ^ __a)) \
& type_min(typeof(__a))) != 0; \
})
/*
* Signed multiplication is rather hard. gcc always follows C99, so
* division is truncated towards 0. This means that we can write the
* overflow check like this:
*
* (a > 0 && (b > MAX/a || b < MIN/a)) ||
* (a < -1 && (b > MIN/a || b < MAX/a) ||
* (a == -1 && b == MIN)
*
* The redundant casts of -1 are to silence an annoying -Wtype-limits
* (included in -Wextra) warning: When the type is u8 or u16, the
* __b_c_e in check_mul_overflow obviously selects
* __unsigned_mul_overflow, but unfortunately gcc still parses this
* code and warns about the limited range of __b.
*/
#define __signed_mul_overflow(a, b, d) ({ \
typeof(a) __a = (a); \
typeof(b) __b = (b); \
typeof(d) __d = (d); \
typeof(a) __tmax = type_max(typeof(a)); \
typeof(a) __tmin = type_min(typeof(a)); \
(void) (&__a == &__b); \
(void) (&__a == __d); \
*__d = (__u64)__a * (__u64)__b; \
(__b > 0 && (__a > __tmax/__b || __a < __tmin/__b)) || \
(__b < (typeof(__b))-1 && (__a > __tmin/__b || __a < __tmax/__b)) || \
(__b == (typeof(__b))-1 && __a == __tmin); \
})
#define check_add_overflow(a, b, d) __must_check_overflow( \
__builtin_choose_expr(is_signed_type(typeof(a)), \
__signed_add_overflow(a, b, d), \
__unsigned_add_overflow(a, b, d)))
#define check_sub_overflow(a, b, d) __must_check_overflow( \
__builtin_choose_expr(is_signed_type(typeof(a)), \
__signed_sub_overflow(a, b, d), \
__unsigned_sub_overflow(a, b, d)))
#define check_mul_overflow(a, b, d) __must_check_overflow( \
__builtin_choose_expr(is_signed_type(typeof(a)), \
__signed_mul_overflow(a, b, d), \
__unsigned_mul_overflow(a, b, d)))
#endif
/* COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW */
#ifndef __noreturn
#ifndef __noreturn
# if __STDC_VERSION__ >= 201112L
# if __STDC_VERSION__ >= 201112L
# if !IS_BIONIC
# if !IS_BIONIC
...
@@ -89,7 +282,4 @@
...
@@ -89,7 +282,4 @@
#define __public __attribute__((visibility("default")))
#define __public __attribute__((visibility("default")))
#endif
#endif
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#endif
/* __LXC_COMPILER_H */
#endif
/* __LXC_COMPILER_H */
src/lxc/confile.c
View file @
db62570f
...
@@ -760,6 +760,8 @@ static int set_config_net_ipv4_address(const char *key, const char *value,
...
@@ -760,6 +760,8 @@ static int set_config_net_ipv4_address(const char *key, const char *value,
}
else
{
}
else
{
inetdev
->
prefix
=
config_ip_prefix
(
&
inetdev
->
addr
);
inetdev
->
prefix
=
config_ip_prefix
(
&
inetdev
->
addr
);
}
}
if
(
inetdev
->
prefix
>
32
)
return
ret_errno
(
EINVAL
);
/* If no broadcast address, let compute one from the
/* If no broadcast address, let compute one from the
* prefix and address.
* prefix and address.
...
@@ -2278,7 +2280,10 @@ static int set_config_mount_auto(const char *key, const char *value,
...
@@ -2278,7 +2280,10 @@ static int set_config_mount_auto(const char *key, const char *value,
if
(
!
container_path
)
if
(
!
container_path
)
return
log_error_errno
(
-
EINVAL
,
EINVAL
,
"Failed to copy shmounts container path"
);
return
log_error_errno
(
-
EINVAL
,
EINVAL
,
"Failed to copy shmounts container path"
);
free_disarm
(
lxc_conf
->
shmount
.
path_host
);
lxc_conf
->
shmount
.
path_host
=
move_ptr
(
host_path
);
lxc_conf
->
shmount
.
path_host
=
move_ptr
(
host_path
);
free_disarm
(
lxc_conf
->
shmount
.
path_cont
);
lxc_conf
->
shmount
.
path_cont
=
move_ptr
(
container_path
);
lxc_conf
->
shmount
.
path_cont
=
move_ptr
(
container_path
);
}
}
}
}
...
@@ -2416,7 +2421,7 @@ static int set_config_console_buffer_size(const char *key, const char *value,
...
@@ -2416,7 +2421,7 @@ static int set_config_console_buffer_size(const char *key, const char *value,
struct
lxc_conf
*
lxc_conf
,
void
*
data
)
struct
lxc_conf
*
lxc_conf
,
void
*
data
)
{
{
int
ret
;
int
ret
;
int64_
t
size
;
long
long
in
t
size
;
uint64_t
buffer_size
,
pgsz
;
uint64_t
buffer_size
,
pgsz
;
if
(
lxc_config_value_empty
(
value
))
{
if
(
lxc_config_value_empty
(
value
))
{
...
@@ -2440,7 +2445,7 @@ static int set_config_console_buffer_size(const char *key, const char *value,
...
@@ -2440,7 +2445,7 @@ static int set_config_console_buffer_size(const char *key, const char *value,
/* must be at least a page size */
/* must be at least a page size */
pgsz
=
lxc_getpagesize
();
pgsz
=
lxc_getpagesize
();
if
((
uint64_t
)
size
<
pgsz
)
{
if
((
uint64_t
)
size
<
pgsz
)
{
NOTICE
(
"Requested ringbuffer size for the console is %
"
PRId64
"
but must be at least %"
PRId64
" bytes. Setting ringbuffer size to %"
PRId64
" bytes"
,
NOTICE
(
"Requested ringbuffer size for the console is %
lld
but must be at least %"
PRId64
" bytes. Setting ringbuffer size to %"
PRId64
" bytes"
,
size
,
pgsz
,
pgsz
);
size
,
pgsz
,
pgsz
);
size
=
pgsz
;
size
=
pgsz
;
}
}
...
@@ -2461,7 +2466,7 @@ static int set_config_console_size(const char *key, const char *value,
...
@@ -2461,7 +2466,7 @@ static int set_config_console_size(const char *key, const char *value,
struct
lxc_conf
*
lxc_conf
,
void
*
data
)
struct
lxc_conf
*
lxc_conf
,
void
*
data
)
{
{
int
ret
;
int
ret
;
int64_
t
size
;
long
long
in
t
size
;
uint64_t
log_size
,
pgsz
;
uint64_t
log_size
,
pgsz
;
if
(
lxc_config_value_empty
(
value
))
{
if
(
lxc_config_value_empty
(
value
))
{
...
@@ -2485,7 +2490,7 @@ static int set_config_console_size(const char *key, const char *value,
...
@@ -2485,7 +2490,7 @@ static int set_config_console_size(const char *key, const char *value,
/* must be at least a page size */
/* must be at least a page size */
pgsz
=
lxc_getpagesize
();
pgsz
=
lxc_getpagesize
();
if
((
uint64_t
)
size
<
pgsz
)
{
if
((
uint64_t
)
size
<
pgsz
)
{
NOTICE
(
"Requested ringbuffer size for the console is %
"
PRId64
"
but must be at least %"
PRId64
" bytes. Setting ringbuffer size to %"
PRId64
" bytes"
,
NOTICE
(
"Requested ringbuffer size for the console is %
lld
but must be at least %"
PRId64
" bytes. Setting ringbuffer size to %"
PRId64
" bytes"
,
size
,
pgsz
,
pgsz
);
size
,
pgsz
,
pgsz
);
size
=
pgsz
;
size
=
pgsz
;
}
}
...
...
src/lxc/string_utils.c
View file @
db62570f
...
@@ -897,13 +897,12 @@ void *must_realloc(void *orig, size_t sz)
...
@@ -897,13 +897,12 @@ void *must_realloc(void *orig, size_t sz)
return
ret
;
return
ret
;
}
}
int
parse_byte_size_string
(
const
char
*
s
,
int64_
t
*
converted
)
int
parse_byte_size_string
(
const
char
*
s
,
long
long
in
t
*
converted
)
{
{
int
ret
,
suffix_len
;
int
ret
,
suffix_len
;
long
long
int
conv
;
long
long
int
conv
,
mltpl
;
int64_t
mltpl
,
overflow
;
char
*
end
;
char
*
end
;
char
dup
[
INTTYPE_TO_STRLEN
(
int64_
t
)];
char
dup
[
INTTYPE_TO_STRLEN
(
long
long
in
t
)];
char
suffix
[
3
]
=
{
0
};
char
suffix
[
3
]
=
{
0
};
if
(
is_empty_string
(
s
))
if
(
is_empty_string
(
s
))
...
@@ -960,11 +959,9 @@ int parse_byte_size_string(const char *s, int64_t *converted)
...
@@ -960,11 +959,9 @@ int parse_byte_size_string(const char *s, int64_t *converted)
else
else
return
ret_errno
(
EINVAL
);
return
ret_errno
(
EINVAL
);
overflow
=
conv
*
mltpl
;
if
(
check_mul_overflow
(
conv
,
mltpl
,
converted
))
if
(
conv
!=
0
&&
(
overflow
/
conv
)
!=
mltpl
)
return
ret_errno
(
ERANGE
);
return
ret_errno
(
ERANGE
);
*
converted
=
overflow
;
return
0
;
return
0
;
}
}
...
...
src/lxc/string_utils.h
View file @
db62570f
...
@@ -81,7 +81,7 @@ __hidden extern int lxc_safe_uint64(const char *numstr, uint64_t *converted, int
...
@@ -81,7 +81,7 @@ __hidden extern int lxc_safe_uint64(const char *numstr, uint64_t *converted, int
__hidden
extern
int
lxc_safe_int64_residual
(
const
char
*
numstr
,
int64_t
*
converted
,
int
base
,
__hidden
extern
int
lxc_safe_int64_residual
(
const
char
*
numstr
,
int64_t
*
converted
,
int
base
,
char
*
residual
,
size_t
residual_len
);
char
*
residual
,
size_t
residual_len
);
/* Handles B, kb, MB, GB. Detects overflows and reports -ERANGE. */
/* Handles B, kb, MB, GB. Detects overflows and reports -ERANGE. */
__hidden
extern
int
parse_byte_size_string
(
const
char
*
s
,
int64_
t
*
converted
);
__hidden
extern
int
parse_byte_size_string
(
const
char
*
s
,
long
long
in
t
*
converted
);
/*
/*
* Concatenate all passed-in strings into one path. Do not fail. If any piece
* Concatenate all passed-in strings into one path. Do not fail. If any piece
...
...
src/tests/lxc-test-utils.c
View file @
db62570f
...
@@ -403,7 +403,7 @@ void test_lxc_string_in_array(void)
...
@@ -403,7 +403,7 @@ void test_lxc_string_in_array(void)
void
test_parse_byte_size_string
(
void
)
void
test_parse_byte_size_string
(
void
)
{
{
int
ret
;
int
ret
;
int64_
t
n
;
long
long
in
t
n
;
ret
=
parse_byte_size_string
(
"0"
,
&
n
);
ret
=
parse_byte_size_string
(
"0"
,
&
n
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment