Message ID | 20250110-lsm-v2-6-bd38035f86bc@suse.com |
---|---|
State | Superseded |
Headers | show |
Series | LSM testing suite | expand |
Hi! > +#include "lsm_common.h" > + > +#define MAX_LSM_NUM 32 > + > +static char lsm_names[MAX_LSM_NUM][BUFSIZ]; > +static size_t lsm_names_count; > +static uint32_t page_size; > +static uint64_t *ids; > +static uint32_t *size; > + > +static void run(void) > +{ > + uint32_t lsm_num; > + size_t count; > + > + memset(ids, 0, sizeof(uint64_t) * MAX_LSM_NUM); > + *size = page_size; > + > + lsm_num = TST_EXP_POSITIVE(lsm_list_modules(ids, size, 0)); If we want to pass the size as page_size here the buffer passed to the syscall would have to be page_size in size. The whole point of passing the size here is to tell the kernel the size of the buffer it can use and it's a pointer because kernel will return the size of the buffer it used back. > + > + TST_EXP_EQ_LI(lsm_num, lsm_names_count); > + TST_EXP_EQ_LI(*size, lsm_num * sizeof(uint64_t)); > + > + for (uint32_t i = 0; i < lsm_num; i++) { > + char *name = NULL; > + > + switch (ids[i]) { > + case LSM_ID_CAPABILITY: > + name = "capability"; > + break; > + case LSM_ID_SELINUX: > + name = "selinux"; > + break; > + case LSM_ID_SMACK: > + name = "smack"; > + break; > + case LSM_ID_TOMOYO: > + name = "tomoyo"; > + break; > + case LSM_ID_APPARMOR: > + name = "apparmor"; > + break; > + case LSM_ID_YAMA: > + name = "yama"; > + break; > + case LSM_ID_LOADPIN: > + name = "loadpin"; > + break; > + case LSM_ID_SAFESETID: > + name = "safesetid"; > + break; > + case LSM_ID_LOCKDOWN: > + name = "lockdown"; > + break; > + case LSM_ID_BPF: > + name = "bpf"; > + break; > + case LSM_ID_LANDLOCK: > + name = "landlock"; > + break; > + case LSM_ID_IMA: > + name = "ima"; > + break; > + case LSM_ID_EVM: > + name = "evm"; > + break; > + case LSM_ID_IPE: > + name = "ipe"; > + break; > + default: > + break; > + } I guess that it may be also a good idea to have an array where we would record which LSM we have seen in the buffer to make sure that we didn't get any of them twice. I suppose that we can turn the lsm_names into a structure and add counters there with: struct lsm_name { int cnt; char name[MAX_LSM_NAME]; }; struct lsm_name lsm_names[MAX_LSM_NUM]; > + if (!name) > + tst_brk(TBROK, "Unsupported LSM: %lu", ids[i]); > + > + for (count = 0; count < lsm_names_count; count++) { > + if (!strcmp(name, lsm_names[count])) { > + tst_res(TPASS, "'%s' is enabled", name); And then we can (assuming we zero the counters at the start of this function) do: if (lsm_names[count].cnt) tst_res(TFAIL, "Duplicated LSM entry %s", lsm_names[count].name); lsm_names[count].cnt++; > + break; > + } > + } > + > + if (count >= lsm_names_count) > + tst_res(TFAIL, "'%s' has not been found", name); > + } > +} > + > +static void setup(void) > +{ > + int fd; > + char *ptr; > + char data[BUFSIZ]; > + > + memset(data, 0, BUFSIZ); > + > + page_size = SAFE_SYSCONF(_SC_PAGESIZE); > + fd = SAFE_OPEN("/sys/kernel/security/lsm", O_RDONLY); > + SAFE_READ(0, fd, data, BUFSIZ); > + SAFE_CLOSE(fd); > + > + ptr = strtok(data, ","); > + > + while (ptr != NULL) { > + strcpy(lsm_names[lsm_names_count], ptr); > + ptr = strtok(NULL, ","); > + lsm_names_count++; > + } > +} > + > +static struct tst_test test = { > + .test_all = run, > + .setup = setup, > + .min_kver = "6.8", > + .bufs = (struct tst_buffers []) { > + {&ids, .size = sizeof(uint64_t) * MAX_LSM_NUM}, > + {&size, .size = sizeof(uint32_t)}, > + {}, > + }, > +}; > > -- > 2.43.0 > > > -- > Mailing list info: https://lists.linux.it/listinfo/ltp
diff --git a/runtest/syscalls b/runtest/syscalls index ae1f430e3dcfebb5167990fcef45b1f3658f6dba..71c644b2da0e55df40ec753c5c31eeb9c474e146 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -760,6 +760,7 @@ lsm_get_self_attr01 lsm_get_self_attr01 lsm_get_self_attr02 lsm_get_self_attr02 lsm_get_self_attr03 lsm_get_self_attr03 lsm_list_modules01 lsm_list_modules01 +lsm_list_modules02 lsm_list_modules02 lstat01 lstat01 lstat01_64 lstat01_64 diff --git a/testcases/kernel/syscalls/lsm/.gitignore b/testcases/kernel/syscalls/lsm/.gitignore index 501d332549a84cceb9741346bdb8b83eb02467c5..766f81fd1c74a10001862f142c02ba251e666ef2 100644 --- a/testcases/kernel/syscalls/lsm/.gitignore +++ b/testcases/kernel/syscalls/lsm/.gitignore @@ -2,3 +2,4 @@ lsm_get_self_attr01 lsm_get_self_attr02 lsm_get_self_attr03 lsm_list_modules01 +lsm_list_modules02 diff --git a/testcases/kernel/syscalls/lsm/lsm_list_modules02.c b/testcases/kernel/syscalls/lsm/lsm_list_modules02.c new file mode 100644 index 0000000000000000000000000000000000000000..b286e6da9581e9ae1cb14f11409f3954568d3c7d --- /dev/null +++ b/testcases/kernel/syscalls/lsm/lsm_list_modules02.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2024 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> + */ + +/*\ + * [Description] + * + * Verify that lsm_list_modules syscall is correctly recognizing LSM(s) enabled + * inside the system. + * + * [Algorithm] + * + * - read enabled LSM(s) inside /sys/kernel/security/lsm file + * - collect LSM IDs using lsm_list_modules syscall + * - compare the results, verifying that LSM(s) IDs are correct + */ + +#include "lsm_common.h" + +#define MAX_LSM_NUM 32 + +static char lsm_names[MAX_LSM_NUM][BUFSIZ]; +static size_t lsm_names_count; +static uint32_t page_size; +static uint64_t *ids; +static uint32_t *size; + +static void run(void) +{ + uint32_t lsm_num; + size_t count; + + memset(ids, 0, sizeof(uint64_t) * MAX_LSM_NUM); + *size = page_size; + + lsm_num = TST_EXP_POSITIVE(lsm_list_modules(ids, size, 0)); + + TST_EXP_EQ_LI(lsm_num, lsm_names_count); + TST_EXP_EQ_LI(*size, lsm_num * sizeof(uint64_t)); + + for (uint32_t i = 0; i < lsm_num; i++) { + char *name = NULL; + + switch (ids[i]) { + case LSM_ID_CAPABILITY: + name = "capability"; + break; + case LSM_ID_SELINUX: + name = "selinux"; + break; + case LSM_ID_SMACK: + name = "smack"; + break; + case LSM_ID_TOMOYO: + name = "tomoyo"; + break; + case LSM_ID_APPARMOR: + name = "apparmor"; + break; + case LSM_ID_YAMA: + name = "yama"; + break; + case LSM_ID_LOADPIN: + name = "loadpin"; + break; + case LSM_ID_SAFESETID: + name = "safesetid"; + break; + case LSM_ID_LOCKDOWN: + name = "lockdown"; + break; + case LSM_ID_BPF: + name = "bpf"; + break; + case LSM_ID_LANDLOCK: + name = "landlock"; + break; + case LSM_ID_IMA: + name = "ima"; + break; + case LSM_ID_EVM: + name = "evm"; + break; + case LSM_ID_IPE: + name = "ipe"; + break; + default: + break; + } + + if (!name) + tst_brk(TBROK, "Unsupported LSM: %lu", ids[i]); + + for (count = 0; count < lsm_names_count; count++) { + if (!strcmp(name, lsm_names[count])) { + tst_res(TPASS, "'%s' is enabled", name); + break; + } + } + + if (count >= lsm_names_count) + tst_res(TFAIL, "'%s' has not been found", name); + } +} + +static void setup(void) +{ + int fd; + char *ptr; + char data[BUFSIZ]; + + memset(data, 0, BUFSIZ); + + page_size = SAFE_SYSCONF(_SC_PAGESIZE); + fd = SAFE_OPEN("/sys/kernel/security/lsm", O_RDONLY); + SAFE_READ(0, fd, data, BUFSIZ); + SAFE_CLOSE(fd); + + ptr = strtok(data, ","); + + while (ptr != NULL) { + strcpy(lsm_names[lsm_names_count], ptr); + ptr = strtok(NULL, ","); + lsm_names_count++; + } +} + +static struct tst_test test = { + .test_all = run, + .setup = setup, + .min_kver = "6.8", + .bufs = (struct tst_buffers []) { + {&ids, .size = sizeof(uint64_t) * MAX_LSM_NUM}, + {&size, .size = sizeof(uint32_t)}, + {}, + }, +};