mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-02 02:34:05 +08:00
d8238f9eb6
The current codebase makes use of the zero-length array language
extension to the C90 standard, but the preferred mechanism to declare
variable-length types such as these ones is a flexible array member[1][2],
introduced in C99:
struct foo {
int stuff;
struct boo array[];
};
By making use of the mechanism above, we will get a compiler warning
in case the flexible array does not occur last in the structure, which
will help us prevent some kind of undefined behavior bugs from being
inadvertently introduced[3] to the codebase from now on.
Also, notice that, dynamic memory allocations won't be affected by
this change:
"Flexible array members have incomplete type, and so the sizeof operator
may not be applied. As a quirk of the original implementation of
zero-length arrays, sizeof evaluates to zero."[1]
sizeof(flexible-array-member) triggers a warning because flexible array
members have incomplete type[1]. There are some instances of code in
which the sizeof operator is being incorrectly/erroneously applied to
zero-length arrays and the result is zero. Such instances may be hiding
some bugs. So, this work (flexible-array member conversions) will also
help to get completely rid of those sorts of issues.
This issue was found with the help of Coccinelle.
[1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
[2] https://github.com/KSPP/linux/issues/21
[3] commit 7649773293
("cxgb3/l2t: Fix undefined behaviour")
Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
80 lines
1.8 KiB
C
80 lines
1.8 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
#define _GNU_SOURCE
|
|
#include <sched.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <signal.h>
|
|
#include <errno.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/prctl.h>
|
|
#include <sys/wait.h>
|
|
|
|
#define pr_err(fmt, ...) \
|
|
({ \
|
|
fprintf(stderr, "%s:%d:" fmt ": %m\n", \
|
|
__func__, __LINE__, ##__VA_ARGS__); \
|
|
1; \
|
|
})
|
|
|
|
#define NSIO 0xb7
|
|
#define NS_GET_USERNS _IO(NSIO, 0x1)
|
|
#define NS_GET_PARENT _IO(NSIO, 0x2)
|
|
|
|
#define __stack_aligned__ __attribute__((aligned(16)))
|
|
struct cr_clone_arg {
|
|
char stack[128] __stack_aligned__;
|
|
char stack_ptr[];
|
|
};
|
|
|
|
static int child(void *args)
|
|
{
|
|
prctl(PR_SET_PDEATHSIG, SIGKILL);
|
|
while (1)
|
|
sleep(1);
|
|
exit(0);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
char *ns_strs[] = {"pid", "user"};
|
|
char path[] = "/proc/0123456789/ns/pid";
|
|
struct cr_clone_arg ca;
|
|
struct stat st1, st2;
|
|
int ns, pns, i;
|
|
pid_t pid;
|
|
|
|
pid = clone(child, ca.stack_ptr, CLONE_NEWUSER | CLONE_NEWPID | SIGCHLD, NULL);
|
|
if (pid < 0)
|
|
return pr_err("clone");
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
snprintf(path, sizeof(path), "/proc/%d/ns/%s", pid, ns_strs[i]);
|
|
ns = open(path, O_RDONLY);
|
|
if (ns < 0)
|
|
return pr_err("Unable to open %s", path);
|
|
|
|
pns = ioctl(ns, NS_GET_PARENT);
|
|
if (pns < 0)
|
|
return pr_err("Unable to get a parent pidns");
|
|
|
|
snprintf(path, sizeof(path), "/proc/self/ns/%s", ns_strs[i]);
|
|
if (stat(path, &st2))
|
|
return pr_err("Unable to stat %s", path);
|
|
if (fstat(pns, &st1))
|
|
return pr_err("Unable to stat the parent pidns");
|
|
if (st1.st_ino != st2.st_ino)
|
|
return pr_err("NS_GET_PARENT returned a wrong namespace");
|
|
|
|
if (ioctl(pns, NS_GET_PARENT) >= 0 || errno != EPERM)
|
|
return pr_err("Don't get EPERM");
|
|
}
|
|
|
|
kill(pid, SIGKILL);
|
|
wait(NULL);
|
|
return 0;
|
|
}
|