From 9c82169208dde516510aaba6bbd8b13976690c5d Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 16 Nov 2023 10:01:21 +0100 Subject: smack: Set SMACK64TRANSMUTE only for dirs in smack_inode_setxattr() Since the SMACK64TRANSMUTE xattr makes sense only for directories, enforce this restriction in smack_inode_setxattr(). Cc: stable@vger.kernel.org Fixes: 5c6d1125f8db ("Smack: Transmute labels on specified directories") # v2.6.38.x Signed-off-by: Roberto Sassu Signed-off-by: Casey Schaufler --- security/smack/smack_lsm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'security') diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 0fdbf04cc258..72b371812a00 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1314,7 +1314,8 @@ static int smack_inode_setxattr(struct mnt_idmap *idmap, check_star = 1; } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { check_priv = 1; - if (size != TRANS_TRUE_SIZE || + if (!S_ISDIR(d_backing_inode(dentry)->i_mode) || + size != TRANS_TRUE_SIZE || strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0) rc = -EINVAL; } else -- cgit v1.2.3 From ac02f007d64eb2769d0bde742aac4d7a5fc6e8a5 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 16 Nov 2023 10:01:22 +0100 Subject: smack: Handle SMACK64TRANSMUTE in smack_inode_setsecurity() If the SMACK64TRANSMUTE xattr is provided, and the inode is a directory, update the in-memory inode flags by setting SMK_INODE_TRANSMUTE. Cc: stable@vger.kernel.org Fixes: 5c6d1125f8db ("Smack: Transmute labels on specified directories") # v2.6.38.x Signed-off-by: Roberto Sassu Signed-off-by: Casey Schaufler --- security/smack/smack_lsm.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'security') diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 72b371812a00..6e5f74813c10 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -2856,6 +2856,15 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, if (value == NULL || size > SMK_LONGLABEL || size == 0) return -EINVAL; + if (strcmp(name, XATTR_SMACK_TRANSMUTE) == 0) { + if (!S_ISDIR(inode->i_mode) || size != TRANS_TRUE_SIZE || + strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0) + return -EINVAL; + + nsp->smk_flags |= SMK_INODE_TRANSMUTE; + return 0; + } + skp = smk_import_entry(value, size); if (IS_ERR(skp)) return PTR_ERR(skp); -- cgit v1.2.3 From 51b15e7990cb5ac42c3aba82f46e1d95e0dd2310 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 16 Nov 2023 10:01:23 +0100 Subject: smack: Always determine inode labels in smack_inode_init_security() The inode_init_security hook is already a good place to initialize the in-memory inode. And that is also what SELinux does. In preparation for this, move the existing smack_inode_init_security() code outside the 'if (xattr)' condition, and set the xattr, if provided. This change does not have any impact on the current code, since every time security_inode_init_security() is called, the initxattr() callback is passed and, thus, xattr is non-NULL. Signed-off-by: Roberto Sassu Signed-off-by: Casey Schaufler --- security/smack/smack_lsm.c | 78 +++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 39 deletions(-) (limited to 'security') diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 6e5f74813c10..2ec3f3345200 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1000,51 +1000,51 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count); int may; - if (xattr) { - /* - * If equal, transmuting already occurred in - * smack_dentry_create_files_as(). No need to check again. - */ - if (tsp->smk_task != tsp->smk_transmuted) { - rcu_read_lock(); - may = smk_access_entry(skp->smk_known, dsp->smk_known, - &skp->smk_rules); - rcu_read_unlock(); - } + /* + * If equal, transmuting already occurred in + * smack_dentry_create_files_as(). No need to check again. + */ + if (tsp->smk_task != tsp->smk_transmuted) { + rcu_read_lock(); + may = smk_access_entry(skp->smk_known, dsp->smk_known, + &skp->smk_rules); + rcu_read_unlock(); + } + + /* + * In addition to having smk_task equal to smk_transmuted, + * if the access rule allows transmutation and the directory + * requests transmutation then by all means transmute. + * Mark the inode as changed. + */ + if ((tsp->smk_task == tsp->smk_transmuted) || + (may > 0 && ((may & MAY_TRANSMUTE) != 0) && + smk_inode_transmutable(dir))) { + struct xattr *xattr_transmute; /* - * In addition to having smk_task equal to smk_transmuted, - * if the access rule allows transmutation and the directory - * requests transmutation then by all means transmute. - * Mark the inode as changed. + * The caller of smack_dentry_create_files_as() + * should have overridden the current cred, so the + * inode label was already set correctly in + * smack_inode_alloc_security(). */ - if ((tsp->smk_task == tsp->smk_transmuted) || - (may > 0 && ((may & MAY_TRANSMUTE) != 0) && - smk_inode_transmutable(dir))) { - struct xattr *xattr_transmute; + if (tsp->smk_task != tsp->smk_transmuted) + isp = dsp; + xattr_transmute = lsm_get_xattr_slot(xattrs, + xattr_count); + if (xattr_transmute) { + xattr_transmute->value = kmemdup(TRANS_TRUE, + TRANS_TRUE_SIZE, + GFP_NOFS); + if (!xattr_transmute->value) + return -ENOMEM; - /* - * The caller of smack_dentry_create_files_as() - * should have overridden the current cred, so the - * inode label was already set correctly in - * smack_inode_alloc_security(). - */ - if (tsp->smk_task != tsp->smk_transmuted) - isp = dsp; - xattr_transmute = lsm_get_xattr_slot(xattrs, - xattr_count); - if (xattr_transmute) { - xattr_transmute->value = kmemdup(TRANS_TRUE, - TRANS_TRUE_SIZE, - GFP_NOFS); - if (!xattr_transmute->value) - return -ENOMEM; - - xattr_transmute->value_len = TRANS_TRUE_SIZE; - xattr_transmute->name = XATTR_SMACK_TRANSMUTE; - } + xattr_transmute->value_len = TRANS_TRUE_SIZE; + xattr_transmute->name = XATTR_SMACK_TRANSMUTE; } + } + if (xattr) { xattr->value = kstrdup(isp->smk_known, GFP_NOFS); if (!xattr->value) return -ENOMEM; -- cgit v1.2.3 From e63d86b8b76437815fc040e8e65da257c28ba922 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 16 Nov 2023 10:01:24 +0100 Subject: smack: Initialize the in-memory inode in smack_inode_init_security() Currently, Smack initializes in-memory new inodes in three steps. It first sets the xattrs in smack_inode_init_security(), fetches them in smack_d_instantiate() and finally, in the same function, sets the in-memory inodes depending on xattr values, unless they are in specially-handled filesystems. Other than being inefficient, this also prevents filesystems not supporting xattrs from working properly since, without xattrs, there is no way to pass the label determined in smack_inode_init_security() to smack_d_instantiate(). Since the LSM infrastructure allows setting and getting the security field without xattrs through the inode_setsecurity and inode_getsecurity hooks, make the inode creation work too, by initializing the in-memory inode earlier in smack_inode_init_security(). Also mark the inode as instantiated, to prevent smack_d_instantiate() from overwriting the security field. As mentioned above, this potentially has impact for inodes in specially-handled filesystems in smack_d_instantiate(), if they are not handled in the same way in smack_inode_init_security(). Filesystems other than tmpfs don't call security_inode_init_security(), so they would be always initialized in smack_d_instantiate(), as before. For tmpfs, the current behavior is to assign to inodes the label '*', but actually that label is overwritten with the one fetched from the SMACK64 xattr, set in smack_inode_init_security() (default: '_'). Initializing the in-memory inode is straightforward: if not transmuting, nothing more needs to be done; if transmuting, overwrite the current inode label with the one from the parent directory, and set SMK_INODE_TRANSMUTE. Finally, set SMK_INODE_INSTANT for all cases, to mark the inode as instantiated. Signed-off-by: Roberto Sassu Signed-off-by: Casey Schaufler --- security/smack/smack_lsm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'security') diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 2ec3f3345200..d52d2a7a813d 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -994,6 +994,7 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, struct xattr *xattrs, int *xattr_count) { struct task_smack *tsp = smack_cred(current_cred()); + struct inode_smack *issp = smack_inode(inode); struct smack_known *skp = smk_of_task(tsp); struct smack_known *isp = smk_of_inode(inode); struct smack_known *dsp = smk_of_inode(dir); @@ -1029,7 +1030,9 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, * smack_inode_alloc_security(). */ if (tsp->smk_task != tsp->smk_transmuted) - isp = dsp; + isp = issp->smk_inode = dsp; + + issp->smk_flags |= SMK_INODE_TRANSMUTE; xattr_transmute = lsm_get_xattr_slot(xattrs, xattr_count); if (xattr_transmute) { @@ -1044,6 +1047,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, } } + issp->smk_flags |= SMK_INODE_INSTANT; + if (xattr) { xattr->value = kstrdup(isp->smk_known, GFP_NOFS); if (!xattr->value) -- cgit v1.2.3 From 1b67772e4e3f16cd647b229cae95fc06d120be08 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Tue, 23 Jan 2024 18:21:06 -0800 Subject: bpf,lsm: Refactor bpf_prog_alloc/bpf_prog_free LSM hooks Based on upstream discussion ([0]), rework existing bpf_prog_alloc_security LSM hook. Rename it to bpf_prog_load and instead of passing bpf_prog_aux, pass proper bpf_prog pointer for a full BPF program struct. Also, we pass bpf_attr union with all the user-provided arguments for BPF_PROG_LOAD command. This will give LSMs as much information as we can basically provide. The hook is also BPF token-aware now, and optional bpf_token struct is passed as a third argument. bpf_prog_load LSM hook is called after a bunch of sanity checks were performed, bpf_prog and bpf_prog_aux were allocated and filled out, but right before performing full-fledged BPF verification step. bpf_prog_free LSM hook is now accepting struct bpf_prog argument, for consistency. SELinux code is adjusted to all new names, types, and signatures. Note, given that bpf_prog_load (previously bpf_prog_alloc) hook can be used by some LSMs to allocate extra security blob, but also by other LSMs to reject BPF program loading, we need to make sure that bpf_prog_free LSM hook is called after bpf_prog_load/bpf_prog_alloc one *even* if the hook itself returned error. If we don't do that, we run the risk of leaking memory. This seems to be possible today when combining SELinux and BPF LSM, as one example, depending on their relative ordering. Also, for BPF LSM setup, add bpf_prog_load and bpf_prog_free to sleepable LSM hooks list, as they are both executed in sleepable context. Also drop bpf_prog_load hook from untrusted, as there is no issue with refcount or anything else anymore, that originally forced us to add it to untrusted list in c0c852dd1876 ("bpf: Do not mark certain LSM hook arguments as trusted"). We now trigger this hook much later and it should not be an issue anymore. [0] https://lore.kernel.org/bpf/9fe88aef7deabbe87d3fc38c4aea3c69.paul@paul-moore.com/ Signed-off-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov Acked-by: Paul Moore Link: https://lore.kernel.org/bpf/20240124022127.2379740-10-andrii@kernel.org --- security/security.c | 25 +++++++++++++++---------- security/selinux/hooks.c | 15 ++++++++------- 2 files changed, 23 insertions(+), 17 deletions(-) (limited to 'security') diff --git a/security/security.c b/security/security.c index 0144a98d3712..eb159da4b146 100644 --- a/security/security.c +++ b/security/security.c @@ -5423,16 +5423,21 @@ int security_bpf_map_alloc(struct bpf_map *map) } /** - * security_bpf_prog_alloc() - Allocate a bpf program LSM blob - * @aux: bpf program aux info struct + * security_bpf_prog_load() - Check if loading of BPF program is allowed + * @prog: BPF program object + * @attr: BPF syscall attributes used to create BPF program + * @token: BPF token used to grant user access to BPF subsystem * - * Initialize the security field inside bpf program. + * Perform an access control check when the kernel loads a BPF program and + * allocates associated BPF program object. This hook is also responsible for + * allocating any required LSM state for the BPF program. * * Return: Returns 0 on success, error on failure. */ -int security_bpf_prog_alloc(struct bpf_prog_aux *aux) +int security_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr, + struct bpf_token *token) { - return call_int_hook(bpf_prog_alloc_security, 0, aux); + return call_int_hook(bpf_prog_load, 0, prog, attr, token); } /** @@ -5447,14 +5452,14 @@ void security_bpf_map_free(struct bpf_map *map) } /** - * security_bpf_prog_free() - Free a bpf program's LSM blob - * @aux: bpf program aux info struct + * security_bpf_prog_free() - Free a BPF program's LSM blob + * @prog: BPF program struct * - * Clean up the security information stored inside bpf prog. + * Clean up the security information stored inside BPF program. */ -void security_bpf_prog_free(struct bpf_prog_aux *aux) +void security_bpf_prog_free(struct bpf_prog *prog) { - call_void_hook(bpf_prog_free_security, aux); + call_void_hook(bpf_prog_free, prog); } #endif /* CONFIG_BPF_SYSCALL */ diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index a6bf90ace84c..6d64fb189b1b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6942,7 +6942,8 @@ static void selinux_bpf_map_free(struct bpf_map *map) kfree(bpfsec); } -static int selinux_bpf_prog_alloc(struct bpf_prog_aux *aux) +static int selinux_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr, + struct bpf_token *token) { struct bpf_security_struct *bpfsec; @@ -6951,16 +6952,16 @@ static int selinux_bpf_prog_alloc(struct bpf_prog_aux *aux) return -ENOMEM; bpfsec->sid = current_sid(); - aux->security = bpfsec; + prog->aux->security = bpfsec; return 0; } -static void selinux_bpf_prog_free(struct bpf_prog_aux *aux) +static void selinux_bpf_prog_free(struct bpf_prog *prog) { - struct bpf_security_struct *bpfsec = aux->security; + struct bpf_security_struct *bpfsec = prog->aux->security; - aux->security = NULL; + prog->aux->security = NULL; kfree(bpfsec); } #endif @@ -7325,7 +7326,7 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = { LSM_HOOK_INIT(bpf_map, selinux_bpf_map), LSM_HOOK_INIT(bpf_prog, selinux_bpf_prog), LSM_HOOK_INIT(bpf_map_free_security, selinux_bpf_map_free), - LSM_HOOK_INIT(bpf_prog_free_security, selinux_bpf_prog_free), + LSM_HOOK_INIT(bpf_prog_free, selinux_bpf_prog_free), #endif #ifdef CONFIG_PERF_EVENTS @@ -7383,7 +7384,7 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = { #endif #ifdef CONFIG_BPF_SYSCALL LSM_HOOK_INIT(bpf_map_alloc_security, selinux_bpf_map_alloc), - LSM_HOOK_INIT(bpf_prog_alloc_security, selinux_bpf_prog_alloc), + LSM_HOOK_INIT(bpf_prog_load, selinux_bpf_prog_load), #endif #ifdef CONFIG_PERF_EVENTS LSM_HOOK_INIT(perf_event_alloc, selinux_perf_event_alloc), -- cgit v1.2.3 From a2431c7eabcf9bd5a1e7a1f7ecded40fdda4a8c5 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Tue, 23 Jan 2024 18:21:07 -0800 Subject: bpf,lsm: Refactor bpf_map_alloc/bpf_map_free LSM hooks Similarly to bpf_prog_alloc LSM hook, rename and extend bpf_map_alloc hook into bpf_map_create, taking not just struct bpf_map, but also bpf_attr and bpf_token, to give a fuller context to LSMs. Unlike bpf_prog_alloc, there is no need to move the hook around, as it currently is firing right before allocating BPF map ID and FD, which seems to be a sweet spot. But like bpf_prog_alloc/bpf_prog_free combo, make sure that bpf_map_free LSM hook is called even if bpf_map_create hook returned error, as if few LSMs are combined together it could be that one LSM successfully allocated security blob for its needs, while subsequent LSM rejected BPF map creation. The former LSM would still need to free up LSM blob, so we need to ensure security_bpf_map_free() is called regardless of the outcome. Signed-off-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov Acked-by: Paul Moore Link: https://lore.kernel.org/bpf/20240124022127.2379740-11-andrii@kernel.org --- security/security.c | 16 ++++++++++------ security/selinux/hooks.c | 7 ++++--- 2 files changed, 14 insertions(+), 9 deletions(-) (limited to 'security') diff --git a/security/security.c b/security/security.c index eb159da4b146..26fcab35b6cd 100644 --- a/security/security.c +++ b/security/security.c @@ -5410,16 +5410,20 @@ int security_bpf_prog(struct bpf_prog *prog) } /** - * security_bpf_map_alloc() - Allocate a bpf map LSM blob - * @map: bpf map + * security_bpf_map_create() - Check if BPF map creation is allowed + * @map: BPF map object + * @attr: BPF syscall attributes used to create BPF map + * @token: BPF token used to grant user access * - * Initialize the security field inside bpf map. + * Do a check when the kernel creates a new BPF map. This is also the + * point where LSM blob is allocated for LSMs that need them. * * Return: Returns 0 on success, error on failure. */ -int security_bpf_map_alloc(struct bpf_map *map) +int security_bpf_map_create(struct bpf_map *map, union bpf_attr *attr, + struct bpf_token *token) { - return call_int_hook(bpf_map_alloc_security, 0, map); + return call_int_hook(bpf_map_create, 0, map, attr, token); } /** @@ -5448,7 +5452,7 @@ int security_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr, */ void security_bpf_map_free(struct bpf_map *map) { - call_void_hook(bpf_map_free_security, map); + call_void_hook(bpf_map_free, map); } /** diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 6d64fb189b1b..3d336a7952f7 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6920,7 +6920,8 @@ static int selinux_bpf_prog(struct bpf_prog *prog) BPF__PROG_RUN, NULL); } -static int selinux_bpf_map_alloc(struct bpf_map *map) +static int selinux_bpf_map_create(struct bpf_map *map, union bpf_attr *attr, + struct bpf_token *token) { struct bpf_security_struct *bpfsec; @@ -7325,7 +7326,7 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = { LSM_HOOK_INIT(bpf, selinux_bpf), LSM_HOOK_INIT(bpf_map, selinux_bpf_map), LSM_HOOK_INIT(bpf_prog, selinux_bpf_prog), - LSM_HOOK_INIT(bpf_map_free_security, selinux_bpf_map_free), + LSM_HOOK_INIT(bpf_map_free, selinux_bpf_map_free), LSM_HOOK_INIT(bpf_prog_free, selinux_bpf_prog_free), #endif @@ -7383,7 +7384,7 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = { LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init), #endif #ifdef CONFIG_BPF_SYSCALL - LSM_HOOK_INIT(bpf_map_alloc_security, selinux_bpf_map_alloc), + LSM_HOOK_INIT(bpf_map_create, selinux_bpf_map_create), LSM_HOOK_INIT(bpf_prog_load, selinux_bpf_prog_load), #endif #ifdef CONFIG_PERF_EVENTS -- cgit v1.2.3 From f568a3d49af9aed813a184353592efe29b0e3d16 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Tue, 23 Jan 2024 18:21:08 -0800 Subject: bpf,lsm: Add BPF token LSM hooks Wire up bpf_token_create and bpf_token_free LSM hooks, which allow to allocate LSM security blob (we add `void *security` field to struct bpf_token for that), but also control who can instantiate BPF token. This follows existing pattern for BPF map and BPF prog. Also add security_bpf_token_allow_cmd() and security_bpf_token_capable() LSM hooks that allow LSM implementation to control and negate (if necessary) BPF token's delegation of a specific bpf_cmd and capability, respectively. Signed-off-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov Acked-by: Paul Moore Link: https://lore.kernel.org/bpf/20240124022127.2379740-12-andrii@kernel.org --- security/security.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'security') diff --git a/security/security.c b/security/security.c index 26fcab35b6cd..73e009e3d937 100644 --- a/security/security.c +++ b/security/security.c @@ -5444,6 +5444,55 @@ int security_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr, return call_int_hook(bpf_prog_load, 0, prog, attr, token); } +/** + * security_bpf_token_create() - Check if creating of BPF token is allowed + * @token: BPF token object + * @attr: BPF syscall attributes used to create BPF token + * @path: path pointing to BPF FS mount point from which BPF token is created + * + * Do a check when the kernel instantiates a new BPF token object from BPF FS + * instance. This is also the point where LSM blob can be allocated for LSMs. + * + * Return: Returns 0 on success, error on failure. + */ +int security_bpf_token_create(struct bpf_token *token, union bpf_attr *attr, + struct path *path) +{ + return call_int_hook(bpf_token_create, 0, token, attr, path); +} + +/** + * security_bpf_token_cmd() - Check if BPF token is allowed to delegate + * requested BPF syscall command + * @token: BPF token object + * @cmd: BPF syscall command requested to be delegated by BPF token + * + * Do a check when the kernel decides whether provided BPF token should allow + * delegation of requested BPF syscall command. + * + * Return: Returns 0 on success, error on failure. + */ +int security_bpf_token_cmd(const struct bpf_token *token, enum bpf_cmd cmd) +{ + return call_int_hook(bpf_token_cmd, 0, token, cmd); +} + +/** + * security_bpf_token_capable() - Check if BPF token is allowed to delegate + * requested BPF-related capability + * @token: BPF token object + * @cap: capabilities requested to be delegated by BPF token + * + * Do a check when the kernel decides whether provided BPF token should allow + * delegation of requested BPF-related capabilities. + * + * Return: Returns 0 on success, error on failure. + */ +int security_bpf_token_capable(const struct bpf_token *token, int cap) +{ + return call_int_hook(bpf_token_capable, 0, token, cap); +} + /** * security_bpf_map_free() - Free a bpf map's LSM blob * @map: bpf map @@ -5465,6 +5514,17 @@ void security_bpf_prog_free(struct bpf_prog *prog) { call_void_hook(bpf_prog_free, prog); } + +/** + * security_bpf_token_free() - Free a BPF token's LSM blob + * @token: BPF token struct + * + * Clean up the security information stored inside BPF token. + */ +void security_bpf_token_free(struct bpf_token *token) +{ + call_void_hook(bpf_token_free, token); +} #endif /* CONFIG_BPF_SYSCALL */ /** -- cgit v1.2.3 From 0054493e5141b16e316b8c52d6aa534397e48b6c Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Tue, 23 Jan 2024 18:21:14 -0800 Subject: bpf,selinux: Allocate bpf_security_struct per BPF token Utilize newly added bpf_token_create/bpf_token_free LSM hooks to allocate struct bpf_security_struct for each BPF token object in SELinux. This just follows similar pattern for BPF prog and map. Signed-off-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov Link: https://lore.kernel.org/bpf/20240124022127.2379740-18-andrii@kernel.org --- security/selinux/hooks.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3d336a7952f7..8dd506ab9b1f 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6965,6 +6965,29 @@ static void selinux_bpf_prog_free(struct bpf_prog *prog) prog->aux->security = NULL; kfree(bpfsec); } + +static int selinux_bpf_token_create(struct bpf_token *token, union bpf_attr *attr, + struct path *path) +{ + struct bpf_security_struct *bpfsec; + + bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL); + if (!bpfsec) + return -ENOMEM; + + bpfsec->sid = current_sid(); + token->security = bpfsec; + + return 0; +} + +static void selinux_bpf_token_free(struct bpf_token *token) +{ + struct bpf_security_struct *bpfsec = token->security; + + token->security = NULL; + kfree(bpfsec); +} #endif struct lsm_blob_sizes selinux_blob_sizes __ro_after_init = { @@ -7328,6 +7351,7 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = { LSM_HOOK_INIT(bpf_prog, selinux_bpf_prog), LSM_HOOK_INIT(bpf_map_free, selinux_bpf_map_free), LSM_HOOK_INIT(bpf_prog_free, selinux_bpf_prog_free), + LSM_HOOK_INIT(bpf_token_free, selinux_bpf_token_free), #endif #ifdef CONFIG_PERF_EVENTS @@ -7386,6 +7410,7 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = { #ifdef CONFIG_BPF_SYSCALL LSM_HOOK_INIT(bpf_map_create, selinux_bpf_map_create), LSM_HOOK_INIT(bpf_prog_load, selinux_bpf_prog_load), + LSM_HOOK_INIT(bpf_token_create, selinux_bpf_token_create), #endif #ifdef CONFIG_PERF_EVENTS LSM_HOOK_INIT(perf_event_alloc, selinux_perf_event_alloc), -- cgit v1.2.3 From 90593caf7db74da2300f7a7056a26ae000b3e7cd Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 18 Jan 2024 20:44:21 -0500 Subject: selinux: reduce the object class calculations at inode init time We only need to call inode_mode_to_security_class() once in selinux_inode_init_security(). Reviewed-by: Stephen Smalley Signed-off-by: Paul Moore --- security/selinux/hooks.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index a6bf90ace84c..48ae90327fa4 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2920,23 +2920,22 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, struct superblock_security_struct *sbsec; struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count); u32 newsid, clen; + u16 newsclass; int rc; char *context; sbsec = selinux_superblock(dir->i_sb); newsid = tsec->create_sid; - - rc = selinux_determine_inode_label(tsec, dir, qstr, - inode_mode_to_security_class(inode->i_mode), - &newsid); + newsclass = inode_mode_to_security_class(inode->i_mode); + rc = selinux_determine_inode_label(tsec, dir, qstr, newsclass, &newsid); if (rc) return rc; /* Possibly defer initialization to selinux_complete_init. */ if (sbsec->flags & SE_SBINITIALIZED) { struct inode_security_struct *isec = selinux_inode(inode); - isec->sclass = inode_mode_to_security_class(inode->i_mode); + isec->sclass = newsclass; isec->sid = newsid; isec->initialized = LABEL_INITIALIZED; } -- cgit v1.2.3 From bfda63fa2243f66e3d07cce2f38cf12d68a2ddf0 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 30 Jan 2024 16:16:29 -0500 Subject: selinux: correct return values in selinux_socket_getpeersec_dgram() Instead of returning -EINVAL if any type of error occurs, limit -EINVAL to only those errors caused by passing a bad/invalid socket or packet/skb. In other cases where everything is correct but there isn't a valid peer label we return -ENOPROTOOPT. This helps make selinux_socket_getpeersec_dgram() more consistent with selinux_socket_getpeersec_stream(). Signed-off-by: Paul Moore --- security/selinux/hooks.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 48ae90327fa4..630ada3d208c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -5193,11 +5193,11 @@ out_len: return err; } -static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) +static int selinux_socket_getpeersec_dgram(struct socket *sock, + struct sk_buff *skb, u32 *secid) { u32 peer_secid = SECSID_NULL; u16 family; - struct inode_security_struct *isec; if (skb && skb->protocol == htons(ETH_P_IP)) family = PF_INET; @@ -5205,19 +5205,21 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff * family = PF_INET6; else if (sock) family = sock->sk->sk_family; - else - goto out; + else { + *secid = SECSID_NULL; + return -EINVAL; + } if (sock && family == PF_UNIX) { + struct inode_security_struct *isec; isec = inode_security_novalidate(SOCK_INODE(sock)); peer_secid = isec->sid; } else if (skb) selinux_skb_peerlbl_sid(skb, family, &peer_secid); -out: *secid = peer_secid; if (peer_secid == SECSID_NULL) - return -EINVAL; + return -ENOPROTOOPT; return 0; } -- cgit v1.2.3 From 7c655bee5cd8e060983bd89460fffc1f9f780cda Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Fri, 2 Feb 2024 17:40:48 +1100 Subject: selinux: only filter copy-up xattrs following initialization Extended attribute copy-up functionality added via 19472b69d639d ("selinux: Implementation for inode_copy_up_xattr() hook") sees "security.selinux" contexts dropped, instead relying on contexts applied via the inode_copy_up() hook. When copy-up takes place during early boot, prior to selinux initialization / policy load, the context stripping can be unwanted and unexpected. With this change, filtering of "security.selinux" xattrs will only occur after selinux initialization. Signed-off-by: David Disseldorp Signed-off-by: Paul Moore --- security/selinux/hooks.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 630ada3d208c..a0fde0641f77 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3533,9 +3533,10 @@ static int selinux_inode_copy_up_xattr(const char *name) { /* The copy_up hook above sets the initial context on an inode, but we * don't then want to overwrite it by blindly copying all the lower - * xattrs up. Instead, we have to filter out SELinux-related xattrs. + * xattrs up. Instead, filter out SELinux-related xattrs following + * policy load. */ - if (strcmp(name, XATTR_NAME_SELINUX) == 0) + if (selinux_initialized() && strcmp(name, XATTR_NAME_SELINUX) == 0) return 1; /* Discard */ /* * Any other attribute apart from SELINUX is not claimed, supported -- cgit v1.2.3 From 69b6d71052b54fb10feba68564ccb41c0f0ce1e9 Mon Sep 17 00:00:00 2001 From: Casey Schaufler Date: Wed, 14 Feb 2024 10:47:06 -0800 Subject: Smack: use init_task_smack() in smack_cred_transfer() smack_cred_transfer() open codes the same initialization as init_task_smack(). Remove the open coding and replace it with a call to init_task_smack(). Signed-off-by: Casey Schaufler --- security/smack/smack_lsm.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'security') diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index d52d2a7a813d..b18b50232947 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -2101,12 +2101,7 @@ static void smack_cred_transfer(struct cred *new, const struct cred *old) struct task_smack *old_tsp = smack_cred(old); struct task_smack *new_tsp = smack_cred(new); - new_tsp->smk_task = old_tsp->smk_task; - new_tsp->smk_forked = old_tsp->smk_task; - mutex_init(&new_tsp->smk_rules_lock); - INIT_LIST_HEAD(&new_tsp->smk_rules); - - /* cbs copy rule list */ + init_task_smack(new_tsp, old_tsp->smk_task, old_tsp->smk_task); } /** -- cgit v1.2.3 From d8bdd795d383a23e38ac48a40d3d223caf47b290 Mon Sep 17 00:00:00 2001 From: Jann Horn Date: Wed, 14 Feb 2024 17:05:38 +0100 Subject: lsm: fix integer overflow in lsm_set_self_attr() syscall security_setselfattr() has an integer overflow bug that leads to out-of-bounds access when userspace provides bogus input: `lctx->ctx_len + sizeof(*lctx)` is checked against `lctx->len` (and, redundantly, also against `size`), but there are no checks on `lctx->ctx_len`. Therefore, userspace can provide an `lsm_ctx` with `->ctx_len` set to a value between `-sizeof(struct lsm_ctx)` and -1, and this bogus `->ctx_len` will then be passed to an LSM module as a buffer length, causing LSM modules to perform out-of-bounds accesses. The following reproducer will demonstrate this under ASAN (if AppArmor is loaded as an LSM): ``` struct lsm_ctx { uint64_t id; uint64_t flags; uint64_t len; uint64_t ctx_len; char ctx[]; }; int main(void) { size_t size = sizeof(struct lsm_ctx); struct lsm_ctx *ctx = malloc(size); ctx->id = 104/*LSM_ID_APPARMOR*/; ctx->flags = 0; ctx->len = size; ctx->ctx_len = -sizeof(struct lsm_ctx); syscall( 460/*__NR_lsm_set_self_attr*/, /*attr=*/ 100/*LSM_ATTR_CURRENT*/, /*ctx=*/ ctx, /*size=*/ size, /*flags=*/ 0 ); } ``` Fixes: a04a1198088a ("LSM: syscalls for current process attributes") Signed-off-by: Jann Horn Acked-by: Casey Schaufler [PM: subj tweak, removed ref to ASAN splat that isn't included] Signed-off-by: Paul Moore --- security/security.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/security/security.c b/security/security.c index 3aaad75c9ce8..7035ee35a393 100644 --- a/security/security.c +++ b/security/security.c @@ -29,6 +29,7 @@ #include #include #include +#include #include /* How many LSMs were built into the kernel? */ @@ -4015,6 +4016,7 @@ int security_setselfattr(unsigned int attr, struct lsm_ctx __user *uctx, struct security_hook_list *hp; struct lsm_ctx *lctx; int rc = LSM_RET_DEFAULT(setselfattr); + u64 required_len; if (flags) return -EINVAL; @@ -4027,8 +4029,9 @@ int security_setselfattr(unsigned int attr, struct lsm_ctx __user *uctx, if (IS_ERR(lctx)) return PTR_ERR(lctx); - if (size < lctx->len || size < lctx->ctx_len + sizeof(*lctx) || - lctx->len < lctx->ctx_len + sizeof(*lctx)) { + if (size < lctx->len || + check_add_overflow(sizeof(*lctx), lctx->ctx_len, &required_len) || + lctx->len < required_len) { rc = -EINVAL; goto free_out; } -- cgit v1.2.3 From bad5247a2c4f7eab6fb922af3362740a562dc665 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:30:49 +0100 Subject: ima: Align ima_inode_post_setattr() definition with LSM infrastructure Change ima_inode_post_setattr() definition, so that it can be registered as implementation of the inode_post_setattr hook (to be introduced). Signed-off-by: Roberto Sassu Reviewed-by: Stefan Berger Reviewed-by: Casey Schaufler Reviewed-by: Mimi Zohar Acked-by: Mimi Zohar Signed-off-by: Paul Moore --- security/integrity/ima/ima_appraise.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'security') diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 870dde67707b..36c2938a5c69 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -629,6 +629,7 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file) * ima_inode_post_setattr - reflect file metadata changes * @idmap: idmap of the mount the inode was found from * @dentry: pointer to the affected dentry + * @ia_valid: for the UID and GID status * * Changes to a dentry's metadata might result in needing to appraise. * @@ -636,7 +637,7 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file) * to lock the inode's i_mutex. */ void ima_inode_post_setattr(struct mnt_idmap *idmap, - struct dentry *dentry) + struct dentry *dentry, int ia_valid) { struct inode *inode = d_backing_inode(dentry); struct integrity_iint_cache *iint; -- cgit v1.2.3 From 0298c5a9b168f0d74ea3bf881301c4bd9252d367 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:30:50 +0100 Subject: ima: Align ima_file_mprotect() definition with LSM infrastructure Change ima_file_mprotect() definition, so that it can be registered as implementation of the file_mprotect hook. Signed-off-by: Roberto Sassu Reviewed-by: Stefan Berger Reviewed-by: Casey Schaufler Reviewed-by: Mimi Zohar Acked-by: Mimi Zohar Signed-off-by: Paul Moore --- security/integrity/ima/ima_main.c | 6 ++++-- security/security.c | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'security') diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index cc1217ac2c6f..b3f5e8401056 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -455,7 +455,8 @@ int ima_file_mmap(struct file *file, unsigned long reqprot, /** * ima_file_mprotect - based on policy, limit mprotect change * @vma: vm_area_struct protection is set to - * @prot: contains the protection that will be applied by the kernel. + * @reqprot: protection requested by the application + * @prot: protection that will be applied by the kernel * * Files can be mmap'ed read/write and later changed to execute to circumvent * IMA's mmap appraisal policy rules. Due to locking issues (mmap semaphore @@ -465,7 +466,8 @@ int ima_file_mmap(struct file *file, unsigned long reqprot, * * On mprotect change success, return 0. On failure, return -EACESS. */ -int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot) +int ima_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, + unsigned long prot) { struct ima_template_desc *template = NULL; struct file *file; diff --git a/security/security.c b/security/security.c index 3aaad75c9ce8..36933ac45d3b 100644 --- a/security/security.c +++ b/security/security.c @@ -2831,7 +2831,7 @@ int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, ret = call_int_hook(file_mprotect, 0, vma, reqprot, prot); if (ret) return ret; - return ima_file_mprotect(vma, prot); + return ima_file_mprotect(vma, reqprot, prot); } /** -- cgit v1.2.3 From fbd0506e5c5874fd52403fd38e3e77d895689870 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:30:51 +0100 Subject: ima: Align ima_inode_setxattr() definition with LSM infrastructure Change ima_inode_setxattr() definition, so that it can be registered as implementation of the inode_setxattr hook. Signed-off-by: Roberto Sassu Reviewed-by: Stefan Berger Reviewed-by: Mimi Zohar Reviewed-by: Casey Schaufler Acked-by: Mimi Zohar Signed-off-by: Paul Moore --- security/integrity/ima/ima_appraise.c | 5 +++-- security/security.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'security') diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 36c2938a5c69..cb2d0d11aa77 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -750,8 +750,9 @@ static int validate_hash_algo(struct dentry *dentry, return -EACCES; } -int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, - const void *xattr_value, size_t xattr_value_len) +int ima_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, + const char *xattr_name, const void *xattr_value, + size_t xattr_value_len, int flags) { const struct evm_ima_xattr_data *xvalue = xattr_value; int digsig = 0; diff --git a/security/security.c b/security/security.c index 36933ac45d3b..b4f6b7467e08 100644 --- a/security/security.c +++ b/security/security.c @@ -2269,7 +2269,7 @@ int security_inode_setxattr(struct mnt_idmap *idmap, ret = cap_inode_setxattr(dentry, name, value, size, flags); if (ret) return ret; - ret = ima_inode_setxattr(dentry, name, value, size); + ret = ima_inode_setxattr(idmap, dentry, name, value, size, flags); if (ret) return ret; return evm_inode_setxattr(idmap, dentry, name, value, size); -- cgit v1.2.3 From 526864dd2f60c16bcdc84e9e7bc6d69d08cfee21 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:30:52 +0100 Subject: ima: Align ima_inode_removexattr() definition with LSM infrastructure Change ima_inode_removexattr() definition, so that it can be registered as implementation of the inode_removexattr hook. Signed-off-by: Roberto Sassu Reviewed-by: Stefan Berger Reviewed-by: Casey Schaufler Reviewed-by: Mimi Zohar Acked-by: Mimi Zohar Signed-off-by: Paul Moore --- security/integrity/ima/ima_appraise.c | 3 ++- security/security.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index cb2d0d11aa77..36abc84ba299 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -790,7 +790,8 @@ int ima_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, return 0; } -int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name) +int ima_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry, + const char *xattr_name) { int result; diff --git a/security/security.c b/security/security.c index b4f6b7467e08..58e20362b679 100644 --- a/security/security.c +++ b/security/security.c @@ -2430,7 +2430,7 @@ int security_inode_removexattr(struct mnt_idmap *idmap, ret = cap_inode_removexattr(idmap, dentry, name); if (ret) return ret; - ret = ima_inode_removexattr(dentry, name); + ret = ima_inode_removexattr(idmap, dentry, name); if (ret) return ret; return evm_inode_removexattr(idmap, dentry, name); -- cgit v1.2.3 From fec5f85e468d6f47851d531ec81f9da821768e00 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:30:53 +0100 Subject: ima: Align ima_post_read_file() definition with LSM infrastructure Change ima_post_read_file() definition, by making "void *buf" a "char *buf", so that it can be registered as implementation of the post_read_file hook. Signed-off-by: Roberto Sassu Reviewed-by: Stefan Berger Reviewed-by: Mimi Zohar Reviewed-by: Casey Schaufler Acked-by: Mimi Zohar Signed-off-by: Paul Moore --- security/integrity/ima/ima_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security') diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index b3f5e8401056..02021ee467d3 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -803,7 +803,7 @@ const int read_idmap[READING_MAX_ID] = { * On success return 0. On integrity appraisal error, assuming the file * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. */ -int ima_post_read_file(struct file *file, void *buf, loff_t size, +int ima_post_read_file(struct file *file, char *buf, loff_t size, enum kernel_read_file_id read_id) { enum ima_hooks func; -- cgit v1.2.3 From 784111d0093e007950cc20033daf3d74ac388821 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:30:54 +0100 Subject: evm: Align evm_inode_post_setattr() definition with LSM infrastructure Change evm_inode_post_setattr() definition, so that it can be registered as implementation of the inode_post_setattr hook (to be introduced). Signed-off-by: Roberto Sassu Reviewed-by: Stefan Berger Reviewed-by: Casey Schaufler Reviewed-by: Mimi Zohar Acked-by: Mimi Zohar Signed-off-by: Paul Moore --- security/integrity/evm/evm_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'security') diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index cc7956d7878b..ac34f21122cd 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -870,6 +870,7 @@ int evm_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry, /** * evm_inode_post_setattr - update 'security.evm' after modifying metadata + * @idmap: idmap of the idmapped mount * @dentry: pointer to the affected dentry * @ia_valid: for the UID and GID status * @@ -879,7 +880,8 @@ int evm_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry, * This function is called from notify_change(), which expects the caller * to lock the inode's i_mutex. */ -void evm_inode_post_setattr(struct dentry *dentry, int ia_valid) +void evm_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + int ia_valid) { if (!evm_revalidate_status(NULL)) return; -- cgit v1.2.3 From 2b6a4054f8c2758cf5c1d78f6ba7006a940b31ce Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:30:55 +0100 Subject: evm: Align evm_inode_setxattr() definition with LSM infrastructure Change evm_inode_setxattr() definition, so that it can be registered as implementation of the inode_setxattr hook. Signed-off-by: Roberto Sassu Reviewed-by: Stefan Berger Reviewed-by: Mimi Zohar Reviewed-by: Casey Schaufler Acked-by: Mimi Zohar Signed-off-by: Paul Moore --- security/integrity/evm/evm_main.c | 3 ++- security/security.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index ac34f21122cd..12ba3207fd31 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -581,6 +581,7 @@ out: * @xattr_name: pointer to the affected extended attribute name * @xattr_value: pointer to the new extended attribute value * @xattr_value_len: pointer to the new extended attribute value length + * @flags: flags to pass into filesystem operations * * Before allowing the 'security.evm' protected xattr to be updated, * verify the existing value is valid. As only the kernel should have @@ -590,7 +591,7 @@ out: */ int evm_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, const char *xattr_name, const void *xattr_value, - size_t xattr_value_len) + size_t xattr_value_len, int flags) { const struct evm_ima_xattr_data *xattr_data = xattr_value; diff --git a/security/security.c b/security/security.c index 58e20362b679..b99c9a69d4c2 100644 --- a/security/security.c +++ b/security/security.c @@ -2272,7 +2272,7 @@ int security_inode_setxattr(struct mnt_idmap *idmap, ret = ima_inode_setxattr(idmap, dentry, name, value, size, flags); if (ret) return ret; - return evm_inode_setxattr(idmap, dentry, name, value, size); + return evm_inode_setxattr(idmap, dentry, name, value, size, flags); } /** -- cgit v1.2.3 From 779cb1947e270504c66a96fc0b7e6e31c748b1e1 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:30:56 +0100 Subject: evm: Align evm_inode_post_setxattr() definition with LSM infrastructure Change evm_inode_post_setxattr() definition, so that it can be registered as implementation of the inode_post_setxattr hook. Signed-off-by: Roberto Sassu Reviewed-by: Stefan Berger Reviewed-by: Mimi Zohar Reviewed-by: Casey Schaufler Acked-by: Mimi Zohar Signed-off-by: Paul Moore --- security/integrity/evm/evm_main.c | 4 +++- security/security.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index 12ba3207fd31..d35143179699 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -753,6 +753,7 @@ bool evm_revalidate_status(const char *xattr_name) * @xattr_name: pointer to the affected extended attribute name * @xattr_value: pointer to the new extended attribute value * @xattr_value_len: pointer to the new extended attribute value length + * @flags: flags to pass into filesystem operations * * Update the HMAC stored in 'security.evm' to reflect the change. * @@ -761,7 +762,8 @@ bool evm_revalidate_status(const char *xattr_name) * i_mutex lock. */ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, - const void *xattr_value, size_t xattr_value_len) + const void *xattr_value, size_t xattr_value_len, + int flags) { if (!evm_revalidate_status(xattr_name)) return; diff --git a/security/security.c b/security/security.c index b99c9a69d4c2..dc188201a4f5 100644 --- a/security/security.c +++ b/security/security.c @@ -2367,7 +2367,7 @@ void security_inode_post_setxattr(struct dentry *dentry, const char *name, if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return; call_void_hook(inode_post_setxattr, dentry, name, value, size, flags); - evm_inode_post_setxattr(dentry, name, value, size); + evm_inode_post_setxattr(dentry, name, value, size, flags); } /** -- cgit v1.2.3 From 314a8dc728d038378795236f6b5199265f921f45 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:30:57 +0100 Subject: security: Align inode_setattr hook definition with EVM Add the idmap parameter to the definition, so that evm_inode_setattr() can be registered as this hook implementation. Signed-off-by: Roberto Sassu Reviewed-by: Stefan Berger Acked-by: Casey Schaufler Reviewed-by: Mimi Zohar Signed-off-by: Paul Moore --- security/security.c | 2 +- security/selinux/hooks.c | 3 ++- security/smack/smack_lsm.c | 4 +++- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'security') diff --git a/security/security.c b/security/security.c index dc188201a4f5..9dc601d45960 100644 --- a/security/security.c +++ b/security/security.c @@ -2215,7 +2215,7 @@ int security_inode_setattr(struct mnt_idmap *idmap, if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - ret = call_int_hook(inode_setattr, 0, dentry, attr); + ret = call_int_hook(inode_setattr, 0, idmap, dentry, attr); if (ret) return ret; return evm_inode_setattr(idmap, dentry, attr); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index a6bf90ace84c..cedb4cbf072e 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3136,7 +3136,8 @@ static int selinux_inode_permission(struct inode *inode, int mask) return rc; } -static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) +static int selinux_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + struct iattr *iattr) { const struct cred *cred = current_cred(); struct inode *inode = d_backing_inode(dentry); diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 0fdbf04cc258..1b6abfdf7173 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1233,12 +1233,14 @@ static int smack_inode_permission(struct inode *inode, int mask) /** * smack_inode_setattr - Smack check for setting attributes + * @idmap: idmap of the mount * @dentry: the object * @iattr: for the force flag * * Returns 0 if access is permitted, an error code otherwise */ -static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr) +static int smack_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + struct iattr *iattr) { struct smk_audit_info ad; int rc; -- cgit v1.2.3 From 77fa6f314f0376176ef6bf3d84403e0d8b54ce28 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:30:58 +0100 Subject: security: Introduce inode_post_setattr hook In preparation for moving IMA and EVM to the LSM infrastructure, introduce the inode_post_setattr hook. At inode_setattr hook, EVM verifies the file's existing HMAC value. At inode_post_setattr, EVM re-calculates the file's HMAC based on the modified file attributes and other file metadata. Other LSMs could similarly take some action after successful file attribute change. The new hook cannot return an error and cannot cause the operation to be reverted. Signed-off-by: Roberto Sassu Reviewed-by: Stefan Berger Reviewed-by: Mimi Zohar Acked-by: Casey Schaufler Acked-by: Christian Brauner Signed-off-by: Paul Moore --- security/security.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'security') diff --git a/security/security.c b/security/security.c index 9dc601d45960..56527d5415e2 100644 --- a/security/security.c +++ b/security/security.c @@ -2222,6 +2222,22 @@ int security_inode_setattr(struct mnt_idmap *idmap, } EXPORT_SYMBOL_GPL(security_inode_setattr); +/** + * security_inode_post_setattr() - Update the inode after a setattr operation + * @idmap: idmap of the mount + * @dentry: file + * @ia_valid: file attributes set + * + * Update inode security field after successful setting file attributes. + */ +void security_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + int ia_valid) +{ + if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) + return; + call_void_hook(inode_post_setattr, idmap, dentry, ia_valid); +} + /** * security_inode_getattr() - Check if getting file attributes is allowed * @path: file -- cgit v1.2.3 From dae52cbf5887ac51c3574648124cfe475a9b3246 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:30:59 +0100 Subject: security: Introduce inode_post_removexattr hook In preparation for moving IMA and EVM to the LSM infrastructure, introduce the inode_post_removexattr hook. At inode_removexattr hook, EVM verifies the file's existing HMAC value. At inode_post_removexattr, EVM re-calculates the file's HMAC with the passed xattr removed and other file metadata. Other LSMs could similarly take some action after successful xattr removal. The new hook cannot return an error and cannot cause the operation to be reverted. Signed-off-by: Roberto Sassu Reviewed-by: Stefan Berger Reviewed-by: Mimi Zohar Reviewed-by: Casey Schaufler Acked-by: Christian Brauner Signed-off-by: Paul Moore --- security/security.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'security') diff --git a/security/security.c b/security/security.c index 56527d5415e2..d77fdd3ca1bc 100644 --- a/security/security.c +++ b/security/security.c @@ -2452,6 +2452,20 @@ int security_inode_removexattr(struct mnt_idmap *idmap, return evm_inode_removexattr(idmap, dentry, name); } +/** + * security_inode_post_removexattr() - Update the inode after a removexattr op + * @dentry: file + * @name: xattr name + * + * Update the inode after a successful removexattr operation. + */ +void security_inode_post_removexattr(struct dentry *dentry, const char *name) +{ + if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) + return; + call_void_hook(inode_post_removexattr, dentry, name); +} + /** * security_inode_need_killpriv() - Check if security_inode_killpriv() required * @dentry: associated dentry -- cgit v1.2.3 From 8f46ff5767b0b18329140d80d6bcabd818f42c4c Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:31:00 +0100 Subject: security: Introduce file_post_open hook In preparation to move IMA and EVM to the LSM infrastructure, introduce the file_post_open hook. Also, export security_file_post_open() for NFS. Based on policy, IMA calculates the digest of the file content and extends the TPM with the digest, verifies the file's integrity based on the digest, and/or includes the file digest in the audit log. LSMs could similarly take action depending on the file content and the access mask requested with open(). The new hook returns a value and can cause the open to be aborted. Signed-off-by: Roberto Sassu Reviewed-by: Stefan Berger Acked-by: Casey Schaufler Reviewed-by: Mimi Zohar Acked-by: Christian Brauner Signed-off-by: Paul Moore --- security/security.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'security') diff --git a/security/security.c b/security/security.c index d77fdd3ca1bc..207405a84902 100644 --- a/security/security.c +++ b/security/security.c @@ -2966,6 +2966,23 @@ int security_file_open(struct file *file) return fsnotify_open_perm(file); } +/** + * security_file_post_open() - Evaluate a file after it has been opened + * @file: the file + * @mask: access mask + * + * Evaluate an opened file and the access mask requested with open(). The hook + * is useful for LSMs that require the file content to be available in order to + * make decisions. + * + * Return: Returns 0 if permission is granted. + */ +int security_file_post_open(struct file *file, int mask) +{ + return call_int_hook(file_post_open, 0, file, mask); +} +EXPORT_SYMBOL_GPL(security_file_post_open); + /** * security_file_truncate() - Check if truncating a file is allowed * @file: file -- cgit v1.2.3 From f09068b5a114ed28d2df2e82a7d30dde0145dc69 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:31:01 +0100 Subject: security: Introduce file_release hook In preparation for moving IMA and EVM to the LSM infrastructure, introduce the file_release hook. IMA calculates at file close the new digest of the file content and writes it to security.ima, so that appraisal at next file access succeeds. The new hook cannot return an error and cannot cause the operation to be reverted. Signed-off-by: Roberto Sassu Acked-by: Christian Brauner Reviewed-by: Stefan Berger Reviewed-by: Mimi Zohar Signed-off-by: Paul Moore --- security/security.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'security') diff --git a/security/security.c b/security/security.c index 207405a84902..99004c44ce55 100644 --- a/security/security.c +++ b/security/security.c @@ -2718,6 +2718,17 @@ int security_file_alloc(struct file *file) return rc; } +/** + * security_file_release() - Perform actions before releasing the file ref + * @file: the file + * + * Perform actions before releasing the last reference to a file. + */ +void security_file_release(struct file *file) +{ + call_void_hook(file_release, file); +} + /** * security_file_free() - Free a file's LSM blob * @file: the file -- cgit v1.2.3 From 08abce60d63fb55f440c393f4508e99064f2fd91 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:31:02 +0100 Subject: security: Introduce path_post_mknod hook In preparation for moving IMA and EVM to the LSM infrastructure, introduce the path_post_mknod hook. IMA-appraisal requires all existing files in policy to have a file hash/signature stored in security.ima. An exception is made for empty files created by mknod, by tagging them as new files. LSMs could also take some action after files are created. The new hook cannot return an error and cannot cause the operation to be reverted. Signed-off-by: Roberto Sassu Acked-by: Casey Schaufler Reviewed-by: Mimi Zohar Acked-by: Christian Brauner Reviewed-by: Stefan Berger Signed-off-by: Paul Moore --- security/security.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'security') diff --git a/security/security.c b/security/security.c index 99004c44ce55..ee4582e1d4d0 100644 --- a/security/security.c +++ b/security/security.c @@ -1800,6 +1800,20 @@ int security_path_mknod(const struct path *dir, struct dentry *dentry, } EXPORT_SYMBOL(security_path_mknod); +/** + * security_path_post_mknod() - Update inode security field after file creation + * @idmap: idmap of the mount + * @dentry: new file + * + * Update inode security field after a file has been created. + */ +void security_path_post_mknod(struct mnt_idmap *idmap, struct dentry *dentry) +{ + if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) + return; + call_void_hook(path_post_mknod, idmap, dentry); +} + /** * security_path_mkdir() - Check if creating a new directory is allowed * @dir: parent directory -- cgit v1.2.3 From a7811e34d100acf24870eb949c5ae3e49dde18b9 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:31:03 +0100 Subject: security: Introduce inode_post_create_tmpfile hook In preparation for moving IMA and EVM to the LSM infrastructure, introduce the inode_post_create_tmpfile hook. As temp files can be made persistent, treat new temp files like other new files, so that the file hash is calculated and stored in the security xattr. LSMs could also take some action after temp files have been created. The new hook cannot return an error and cannot cause the operation to be canceled. Signed-off-by: Roberto Sassu Acked-by: Casey Schaufler Reviewed-by: Mimi Zohar Acked-by: Christian Brauner Reviewed-by: Stefan Berger Signed-off-by: Paul Moore --- security/security.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'security') diff --git a/security/security.c b/security/security.c index ee4582e1d4d0..710db090aa8b 100644 --- a/security/security.c +++ b/security/security.c @@ -2013,6 +2013,21 @@ int security_inode_create(struct inode *dir, struct dentry *dentry, } EXPORT_SYMBOL_GPL(security_inode_create); +/** + * security_inode_post_create_tmpfile() - Update inode security of new tmpfile + * @idmap: idmap of the mount + * @inode: inode of the new tmpfile + * + * Update inode security data after a tmpfile has been created. + */ +void security_inode_post_create_tmpfile(struct mnt_idmap *idmap, + struct inode *inode) +{ + if (unlikely(IS_PRIVATE(inode))) + return; + call_void_hook(inode_post_create_tmpfile, idmap, inode); +} + /** * security_inode_link() - Check if creating a hard link is allowed * @old_dentry: existing file -- cgit v1.2.3 From 8b9d0b825c6573d654c8b8039ea79920926305c2 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:31:04 +0100 Subject: security: Introduce inode_post_set_acl hook In preparation for moving IMA and EVM to the LSM infrastructure, introduce the inode_post_set_acl hook. At inode_set_acl hook, EVM verifies the file's existing HMAC value. At inode_post_set_acl, EVM re-calculates the file's HMAC based on the modified POSIX ACL and other file metadata. Other LSMs could similarly take some action after successful POSIX ACL change. The new hook cannot return an error and cannot cause the operation to be reverted. Signed-off-by: Roberto Sassu Reviewed-by: Stefan Berger Acked-by: Casey Schaufler Reviewed-by: Mimi Zohar Acked-by: Christian Brauner Signed-off-by: Paul Moore --- security/security.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'security') diff --git a/security/security.c b/security/security.c index 710db090aa8b..52f62f785087 100644 --- a/security/security.c +++ b/security/security.c @@ -2350,6 +2350,23 @@ int security_inode_set_acl(struct mnt_idmap *idmap, return evm_inode_set_acl(idmap, dentry, acl_name, kacl); } +/** + * security_inode_post_set_acl() - Update inode security from posix acls set + * @dentry: file + * @acl_name: acl name + * @kacl: acl struct + * + * Update inode security data after successfully setting posix acls on @dentry. + * The posix acls in @kacl are identified by @acl_name. + */ +void security_inode_post_set_acl(struct dentry *dentry, const char *acl_name, + struct posix_acl *kacl) +{ + if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) + return; + call_void_hook(inode_post_set_acl, dentry, acl_name, kacl); +} + /** * security_inode_get_acl() - Check if reading posix acls is allowed * @idmap: idmap of the mount -- cgit v1.2.3 From 2d705d8024143c272a764320c880ccd3230bb699 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:31:05 +0100 Subject: security: Introduce inode_post_remove_acl hook In preparation for moving IMA and EVM to the LSM infrastructure, introduce the inode_post_remove_acl hook. At inode_remove_acl hook, EVM verifies the file's existing HMAC value. At inode_post_remove_acl, EVM re-calculates the file's HMAC with the passed POSIX ACL removed and other file metadata. Other LSMs could similarly take some action after successful POSIX ACL removal. The new hook cannot return an error and cannot cause the operation to be reverted. Signed-off-by: Roberto Sassu Reviewed-by: Stefan Berger Acked-by: Casey Schaufler Reviewed-by: Mimi Zohar Acked-by: Christian Brauner Signed-off-by: Paul Moore --- security/security.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'security') diff --git a/security/security.c b/security/security.c index 52f62f785087..3bed660fc950 100644 --- a/security/security.c +++ b/security/security.c @@ -2413,6 +2413,23 @@ int security_inode_remove_acl(struct mnt_idmap *idmap, return evm_inode_remove_acl(idmap, dentry, acl_name); } +/** + * security_inode_post_remove_acl() - Update inode security after rm posix acls + * @idmap: idmap of the mount + * @dentry: file + * @acl_name: acl name + * + * Update inode security data after successfully removing posix acls on + * @dentry in @idmap. The posix acls are identified by @acl_name. + */ +void security_inode_post_remove_acl(struct mnt_idmap *idmap, + struct dentry *dentry, const char *acl_name) +{ + if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) + return; + call_void_hook(inode_post_remove_acl, idmap, dentry, acl_name); +} + /** * security_inode_post_setxattr() - Update the inode after a setxattr operation * @dentry: file -- cgit v1.2.3 From b8d997032a46fcf47d5bda011c0d1e87b20c08ba Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:31:06 +0100 Subject: security: Introduce key_post_create_or_update hook In preparation for moving IMA and EVM to the LSM infrastructure, introduce the key_post_create_or_update hook. Depending on policy, IMA measures the key content after creation or update, so that remote verifiers are aware of the operation. Other LSMs could similarly take some action after successful key creation or update. The new hook cannot return an error and cannot cause the operation to be reverted. Signed-off-by: Roberto Sassu Reviewed-by: Stefan Berger Acked-by: Casey Schaufler Reviewed-by: Mimi Zohar Signed-off-by: Paul Moore --- security/keys/key.c | 7 ++++++- security/security.c | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'security') diff --git a/security/keys/key.c b/security/keys/key.c index 5b10641debd5..31a8b9408b7c 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -930,6 +930,8 @@ static key_ref_t __key_create_or_update(key_ref_t keyring_ref, goto error_link_end; } + security_key_post_create_or_update(keyring, key, payload, plen, flags, + true); ima_post_key_create_or_update(keyring, key, payload, plen, flags, true); @@ -963,10 +965,13 @@ error: key_ref = __key_update(key_ref, &prep); - if (!IS_ERR(key_ref)) + if (!IS_ERR(key_ref)) { + security_key_post_create_or_update(keyring, key, payload, plen, + flags, false); ima_post_key_create_or_update(keyring, key, payload, plen, flags, false); + } goto error_free_prep; } diff --git a/security/security.c b/security/security.c index 3bed660fc950..6c23c620e3c1 100644 --- a/security/security.c +++ b/security/security.c @@ -5453,6 +5453,25 @@ int security_key_getsecurity(struct key *key, char **buffer) *buffer = NULL; return call_int_hook(key_getsecurity, 0, key, buffer); } + +/** + * security_key_post_create_or_update() - Notification of key create or update + * @keyring: keyring to which the key is linked to + * @key: created or updated key + * @payload: data used to instantiate or update the key + * @payload_len: length of payload + * @flags: key flags + * @create: flag indicating whether the key was created or updated + * + * Notify the caller of a key creation or update. + */ +void security_key_post_create_or_update(struct key *keyring, struct key *key, + const void *payload, size_t payload_len, + unsigned long flags, bool create) +{ + call_void_hook(key_post_create_or_update, keyring, key, payload, + payload_len, flags, create); +} #endif /* CONFIG_KEYS */ #ifdef CONFIG_AUDIT -- cgit v1.2.3 From 06cca5110774f7b59a1685431ac697865588f4ca Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:31:07 +0100 Subject: integrity: Move integrity_kernel_module_request() to IMA In preparation for removing the 'integrity' LSM, move integrity_kernel_module_request() to IMA, and rename it to ima_kernel_module_request(). Rewrite the function documentation, to explain better what the problem is. Compile it conditionally if CONFIG_INTEGRITY_ASYMMETRIC_KEYS is enabled, and call it from security.c (removed afterwards with the move of IMA to the LSM infrastructure). Adding this hook cannot be avoided, since IMA has no control on the flags passed to crypto_alloc_sig() in public_key_verify_signature(), and thus cannot pass CRYPTO_NOLOAD, which solved the problem for EVM hashing with commit e2861fa71641 ("evm: Don't deadlock if a crypto algorithm is unavailable"). EVM alone does not need to implement this hook, first because there is no mutex to deadlock, and second because even if it had it, there should be a recursive call. However, since verification from EVM can be initiated only by setting inode metadata, deadlock would occur if modprobe would do the same while loading a kernel module (which is unlikely). Signed-off-by: Roberto Sassu Reviewed-by: Stefan Berger Reviewed-by: Mimi Zohar Acked-by: Mimi Zohar Signed-off-by: Paul Moore --- security/integrity/digsig_asymmetric.c | 23 ----------------------- security/integrity/ima/ima_main.c | 33 +++++++++++++++++++++++++++++++++ security/security.c | 2 +- 3 files changed, 34 insertions(+), 24 deletions(-) (limited to 'security') diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c index 895f4b9ce8c6..de603cf42ac7 100644 --- a/security/integrity/digsig_asymmetric.c +++ b/security/integrity/digsig_asymmetric.c @@ -132,26 +132,3 @@ out: pr_debug("%s() = %d\n", __func__, ret); return ret; } - -/** - * integrity_kernel_module_request - prevent crypto-pkcs1pad(rsa,*) requests - * @kmod_name: kernel module name - * - * We have situation, when public_key_verify_signature() in case of RSA - * algorithm use alg_name to store internal information in order to - * construct an algorithm on the fly, but crypto_larval_lookup() will try - * to use alg_name in order to load kernel module with same name. - * Since we don't have any real "crypto-pkcs1pad(rsa,*)" kernel modules, - * we are safe to fail such module request from crypto_larval_lookup(). - * - * In this way we prevent modprobe execution during digsig verification - * and avoid possible deadlock if modprobe and/or it's dependencies - * also signed with digsig. - */ -int integrity_kernel_module_request(char *kmod_name) -{ - if (strncmp(kmod_name, "crypto-pkcs1pad(rsa,", 20) == 0) - return -EINVAL; - - return 0; -} diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 02021ee467d3..3891b83efdb3 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -1091,6 +1091,39 @@ int ima_measure_critical_data(const char *event_label, } EXPORT_SYMBOL_GPL(ima_measure_critical_data); +#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS + +/** + * ima_kernel_module_request - Prevent crypto-pkcs1pad(rsa,*) requests + * @kmod_name: kernel module name + * + * Avoid a verification loop where verifying the signature of the modprobe + * binary requires executing modprobe itself. Since the modprobe iint->mutex + * is already held when the signature verification is performed, a deadlock + * occurs as soon as modprobe is executed within the critical region, since + * the same lock cannot be taken again. + * + * This happens when public_key_verify_signature(), in case of RSA algorithm, + * use alg_name to store internal information in order to construct an + * algorithm on the fly, but crypto_larval_lookup() will try to use alg_name + * in order to load a kernel module with same name. + * + * Since we don't have any real "crypto-pkcs1pad(rsa,*)" kernel modules, + * we are safe to fail such module request from crypto_larval_lookup(), and + * avoid the verification loop. + * + * Return: Zero if it is safe to load the kernel module, -EINVAL otherwise. + */ +int ima_kernel_module_request(char *kmod_name) +{ + if (strncmp(kmod_name, "crypto-pkcs1pad(rsa,", 20) == 0) + return -EINVAL; + + return 0; +} + +#endif /* CONFIG_INTEGRITY_ASYMMETRIC_KEYS */ + static int __init init_ima(void) { int error; diff --git a/security/security.c b/security/security.c index 6c23c620e3c1..bc3c6790aeaf 100644 --- a/security/security.c +++ b/security/security.c @@ -3249,7 +3249,7 @@ int security_kernel_module_request(char *kmod_name) ret = call_int_hook(kernel_module_request, 0, kmod_name); if (ret) return ret; - return integrity_kernel_module_request(kmod_name); + return ima_kernel_module_request(kmod_name); } /** -- cgit v1.2.3 From cd3cec0a02c7338ce2901c574f3935b8f6984aab Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:31:08 +0100 Subject: ima: Move to LSM infrastructure Move hardcoded IMA function calls (not appraisal-specific functions) from various places in the kernel to the LSM infrastructure, by introducing a new LSM named 'ima' (at the end of the LSM list and always enabled like 'integrity'). Having IMA before EVM in the Makefile is sufficient to preserve the relative order of the new 'ima' LSM in respect to the upcoming 'evm' LSM, and thus the order of IMA and EVM function calls as when they were hardcoded. Make moved functions as static (except ima_post_key_create_or_update(), which is not in ima_main.c), and register them as implementation of the respective hooks in the new function init_ima_lsm(). Select CONFIG_SECURITY_PATH, to ensure that the path-based LSM hook path_post_mknod is always available and ima_post_path_mknod() is always executed to mark files as new, as before the move. A slight difference is that IMA and EVM functions registered for the inode_post_setattr, inode_post_removexattr, path_post_mknod, inode_post_create_tmpfile, inode_post_set_acl and inode_post_remove_acl won't be executed for private inodes. Since those inodes are supposed to be fs-internal, they should not be of interest to IMA or EVM. The S_PRIVATE flag is used for anonymous inodes, hugetlbfs, reiserfs xattrs, XFS scrub and kernel-internal tmpfs files. Conditionally register ima_post_key_create_or_update() if CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS is enabled. Also, conditionally register ima_kernel_module_request() if CONFIG_INTEGRITY_ASYMMETRIC_KEYS is enabled. Finally, add the LSM_ID_IMA case in lsm_list_modules_test.c. Signed-off-by: Roberto Sassu Acked-by: Chuck Lever Acked-by: Casey Schaufler Acked-by: Christian Brauner Reviewed-by: Stefan Berger Reviewed-by: Mimi Zohar Acked-by: Mimi Zohar Signed-off-by: Paul Moore --- security/integrity/Makefile | 1 + security/integrity/ima/Kconfig | 1 + security/integrity/ima/ima.h | 6 +++ security/integrity/ima/ima_main.c | 78 ++++++++++++++++++++++++++++----------- security/integrity/integrity.h | 1 + security/keys/key.c | 9 +---- security/security.c | 63 ++++++------------------------- 7 files changed, 79 insertions(+), 80 deletions(-) (limited to 'security') diff --git a/security/integrity/Makefile b/security/integrity/Makefile index d0ffe37dc1d6..92b63039c654 100644 --- a/security/integrity/Makefile +++ b/security/integrity/Makefile @@ -18,5 +18,6 @@ integrity-$(CONFIG_LOAD_IPL_KEYS) += platform_certs/load_ipl_s390.o integrity-$(CONFIG_LOAD_PPC_KEYS) += platform_certs/efi_parser.o \ platform_certs/load_powerpc.o \ platform_certs/keyring_handler.o +# The relative order of the 'ima' and 'evm' LSMs depends on the order below. obj-$(CONFIG_IMA) += ima/ obj-$(CONFIG_EVM) += evm/ diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index b98bfe9efd0c..475c32615006 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -8,6 +8,7 @@ config IMA select CRYPTO_HMAC select CRYPTO_SHA1 select CRYPTO_HASH_INFO + select SECURITY_PATH select TCG_TPM if HAS_IOMEM select TCG_TIS if TCG_TPM && X86 select TCG_CRB if TCG_TPM && ACPI diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index c29db699c996..c0412100023e 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -127,6 +127,12 @@ void ima_load_kexec_buffer(void); static inline void ima_load_kexec_buffer(void) {} #endif /* CONFIG_HAVE_IMA_KEXEC */ +#ifdef CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS +void ima_post_key_create_or_update(struct key *keyring, struct key *key, + const void *payload, size_t plen, + unsigned long flags, bool create); +#endif + /* * The default binary_runtime_measurements list format is defined as the * platform native format. The canonical format is defined as little-endian. diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 3891b83efdb3..d0826e864c29 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -189,7 +189,7 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint, * * Flag files that changed, based on i_version */ -void ima_file_free(struct file *file) +static void ima_file_free(struct file *file) { struct inode *inode = file_inode(file); struct integrity_iint_cache *iint; @@ -427,8 +427,8 @@ out: * On success return 0. On integrity appraisal error, assuming the file * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. */ -int ima_file_mmap(struct file *file, unsigned long reqprot, - unsigned long prot, unsigned long flags) +static int ima_file_mmap(struct file *file, unsigned long reqprot, + unsigned long prot, unsigned long flags) { u32 secid; int ret; @@ -466,8 +466,8 @@ int ima_file_mmap(struct file *file, unsigned long reqprot, * * On mprotect change success, return 0. On failure, return -EACESS. */ -int ima_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, - unsigned long prot) +static int ima_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, + unsigned long prot) { struct ima_template_desc *template = NULL; struct file *file; @@ -525,7 +525,7 @@ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, * On success return 0. On integrity appraisal error, assuming the file * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. */ -int ima_bprm_check(struct linux_binprm *bprm) +static int ima_bprm_check(struct linux_binprm *bprm) { int ret; u32 secid; @@ -551,7 +551,7 @@ int ima_bprm_check(struct linux_binprm *bprm) * On success return 0. On integrity appraisal error, assuming the file * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. */ -int ima_file_check(struct file *file, int mask) +static int ima_file_check(struct file *file, int mask) { u32 secid; @@ -560,7 +560,6 @@ int ima_file_check(struct file *file, int mask) mask & (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND), FILE_CHECK); } -EXPORT_SYMBOL_GPL(ima_file_check); static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf, size_t buf_size) @@ -685,8 +684,9 @@ EXPORT_SYMBOL_GPL(ima_inode_hash); * Skip calling process_measurement(), but indicate which newly, created * tmpfiles are in policy. */ -void ima_post_create_tmpfile(struct mnt_idmap *idmap, - struct inode *inode) +static void ima_post_create_tmpfile(struct mnt_idmap *idmap, + struct inode *inode) + { struct integrity_iint_cache *iint; int must_appraise; @@ -717,8 +717,7 @@ void ima_post_create_tmpfile(struct mnt_idmap *idmap, * Mark files created via the mknodat syscall as new, so that the * file data can be written later. */ -void ima_post_path_mknod(struct mnt_idmap *idmap, - struct dentry *dentry) +static void ima_post_path_mknod(struct mnt_idmap *idmap, struct dentry *dentry) { struct integrity_iint_cache *iint; struct inode *inode = dentry->d_inode; @@ -753,8 +752,8 @@ void ima_post_path_mknod(struct mnt_idmap *idmap, * * For permission return 0, otherwise return -EACCES. */ -int ima_read_file(struct file *file, enum kernel_read_file_id read_id, - bool contents) +static int ima_read_file(struct file *file, enum kernel_read_file_id read_id, + bool contents) { enum ima_hooks func; u32 secid; @@ -803,8 +802,8 @@ const int read_idmap[READING_MAX_ID] = { * On success return 0. On integrity appraisal error, assuming the file * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. */ -int ima_post_read_file(struct file *file, char *buf, loff_t size, - enum kernel_read_file_id read_id) +static int ima_post_read_file(struct file *file, char *buf, loff_t size, + enum kernel_read_file_id read_id) { enum ima_hooks func; u32 secid; @@ -837,7 +836,7 @@ int ima_post_read_file(struct file *file, char *buf, loff_t size, * * For permission return 0, otherwise return -EACCES. */ -int ima_load_data(enum kernel_load_data_id id, bool contents) +static int ima_load_data(enum kernel_load_data_id id, bool contents) { bool ima_enforce, sig_enforce; @@ -891,9 +890,9 @@ int ima_load_data(enum kernel_load_data_id id, bool contents) * On success return 0. On integrity appraisal error, assuming the file * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. */ -int ima_post_load_data(char *buf, loff_t size, - enum kernel_load_data_id load_id, - char *description) +static int ima_post_load_data(char *buf, loff_t size, + enum kernel_load_data_id load_id, + char *description) { if (load_id == LOADING_FIRMWARE) { if ((ima_appraise & IMA_APPRAISE_FIRMWARE) && @@ -1114,7 +1113,7 @@ EXPORT_SYMBOL_GPL(ima_measure_critical_data); * * Return: Zero if it is safe to load the kernel module, -EINVAL otherwise. */ -int ima_kernel_module_request(char *kmod_name) +static int ima_kernel_module_request(char *kmod_name) { if (strncmp(kmod_name, "crypto-pkcs1pad(rsa,", 20) == 0) return -EINVAL; @@ -1155,4 +1154,41 @@ static int __init init_ima(void) return error; } +static struct security_hook_list ima_hooks[] __ro_after_init = { + LSM_HOOK_INIT(bprm_check_security, ima_bprm_check), + LSM_HOOK_INIT(file_post_open, ima_file_check), + LSM_HOOK_INIT(inode_post_create_tmpfile, ima_post_create_tmpfile), + LSM_HOOK_INIT(file_release, ima_file_free), + LSM_HOOK_INIT(mmap_file, ima_file_mmap), + LSM_HOOK_INIT(file_mprotect, ima_file_mprotect), + LSM_HOOK_INIT(kernel_load_data, ima_load_data), + LSM_HOOK_INIT(kernel_post_load_data, ima_post_load_data), + LSM_HOOK_INIT(kernel_read_file, ima_read_file), + LSM_HOOK_INIT(kernel_post_read_file, ima_post_read_file), + LSM_HOOK_INIT(path_post_mknod, ima_post_path_mknod), +#ifdef CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS + LSM_HOOK_INIT(key_post_create_or_update, ima_post_key_create_or_update), +#endif +#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS + LSM_HOOK_INIT(kernel_module_request, ima_kernel_module_request), +#endif +}; + +static const struct lsm_id ima_lsmid = { + .name = "ima", + .id = LSM_ID_IMA, +}; + +static int __init init_ima_lsm(void) +{ + security_add_hooks(ima_hooks, ARRAY_SIZE(ima_hooks), &ima_lsmid); + return 0; +} + +DEFINE_LSM(ima) = { + .name = "ima", + .init = init_ima_lsm, + .order = LSM_ORDER_LAST, +}; + late_initcall(init_ima); /* Start IMA after the TPM is available */ diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 9561db7cf6b4..59eaddd84434 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -18,6 +18,7 @@ #include #include #include +#include /* iint action cache flags */ #define IMA_MEASURE 0x00000001 diff --git a/security/keys/key.c b/security/keys/key.c index 31a8b9408b7c..560790038329 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include "internal.h" @@ -932,8 +931,6 @@ static key_ref_t __key_create_or_update(key_ref_t keyring_ref, security_key_post_create_or_update(keyring, key, payload, plen, flags, true); - ima_post_key_create_or_update(keyring, key, payload, plen, - flags, true); key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); @@ -965,13 +962,9 @@ error: key_ref = __key_update(key_ref, &prep); - if (!IS_ERR(key_ref)) { + if (!IS_ERR(key_ref)) security_key_post_create_or_update(keyring, key, payload, plen, flags, false); - ima_post_key_create_or_update(keyring, key, - payload, plen, - flags, false); - } goto error_free_prep; } diff --git a/security/security.c b/security/security.c index bc3c6790aeaf..8495890a5a37 100644 --- a/security/security.c +++ b/security/security.c @@ -50,7 +50,8 @@ (IS_ENABLED(CONFIG_SECURITY_SAFESETID) ? 1 : 0) + \ (IS_ENABLED(CONFIG_SECURITY_LOCKDOWN_LSM) ? 1 : 0) + \ (IS_ENABLED(CONFIG_BPF_LSM) ? 1 : 0) + \ - (IS_ENABLED(CONFIG_SECURITY_LANDLOCK) ? 1 : 0)) + (IS_ENABLED(CONFIG_SECURITY_LANDLOCK) ? 1 : 0) + \ + (IS_ENABLED(CONFIG_IMA) ? 1 : 0)) /* * These are descriptions of the reasons that can be passed to the @@ -1182,12 +1183,7 @@ int security_bprm_creds_from_file(struct linux_binprm *bprm, const struct file * */ int security_bprm_check(struct linux_binprm *bprm) { - int ret; - - ret = call_int_hook(bprm_check_security, 0, bprm); - if (ret) - return ret; - return ima_bprm_check(bprm); + return call_int_hook(bprm_check_security, 0, bprm); } /** @@ -2895,13 +2891,8 @@ static inline unsigned long mmap_prot(struct file *file, unsigned long prot) int security_mmap_file(struct file *file, unsigned long prot, unsigned long flags) { - unsigned long prot_adj = mmap_prot(file, prot); - int ret; - - ret = call_int_hook(mmap_file, 0, file, prot, prot_adj, flags); - if (ret) - return ret; - return ima_file_mmap(file, prot, prot_adj, flags); + return call_int_hook(mmap_file, 0, file, prot, mmap_prot(file, prot), + flags); } /** @@ -2930,12 +2921,7 @@ int security_mmap_addr(unsigned long addr) int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, unsigned long prot) { - int ret; - - ret = call_int_hook(file_mprotect, 0, vma, reqprot, prot); - if (ret) - return ret; - return ima_file_mprotect(vma, reqprot, prot); + return call_int_hook(file_mprotect, 0, vma, reqprot, prot); } /** @@ -3244,12 +3230,7 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode) */ int security_kernel_module_request(char *kmod_name) { - int ret; - - ret = call_int_hook(kernel_module_request, 0, kmod_name); - if (ret) - return ret; - return ima_kernel_module_request(kmod_name); + return call_int_hook(kernel_module_request, 0, kmod_name); } /** @@ -3265,12 +3246,7 @@ int security_kernel_module_request(char *kmod_name) int security_kernel_read_file(struct file *file, enum kernel_read_file_id id, bool contents) { - int ret; - - ret = call_int_hook(kernel_read_file, 0, file, id, contents); - if (ret) - return ret; - return ima_read_file(file, id, contents); + return call_int_hook(kernel_read_file, 0, file, id, contents); } EXPORT_SYMBOL_GPL(security_kernel_read_file); @@ -3290,12 +3266,7 @@ EXPORT_SYMBOL_GPL(security_kernel_read_file); int security_kernel_post_read_file(struct file *file, char *buf, loff_t size, enum kernel_read_file_id id) { - int ret; - - ret = call_int_hook(kernel_post_read_file, 0, file, buf, size, id); - if (ret) - return ret; - return ima_post_read_file(file, buf, size, id); + return call_int_hook(kernel_post_read_file, 0, file, buf, size, id); } EXPORT_SYMBOL_GPL(security_kernel_post_read_file); @@ -3310,12 +3281,7 @@ EXPORT_SYMBOL_GPL(security_kernel_post_read_file); */ int security_kernel_load_data(enum kernel_load_data_id id, bool contents) { - int ret; - - ret = call_int_hook(kernel_load_data, 0, id, contents); - if (ret) - return ret; - return ima_load_data(id, contents); + return call_int_hook(kernel_load_data, 0, id, contents); } EXPORT_SYMBOL_GPL(security_kernel_load_data); @@ -3337,13 +3303,8 @@ int security_kernel_post_load_data(char *buf, loff_t size, enum kernel_load_data_id id, char *description) { - int ret; - - ret = call_int_hook(kernel_post_load_data, 0, buf, size, id, - description); - if (ret) - return ret; - return ima_post_load_data(buf, size, id, description); + return call_int_hook(kernel_post_load_data, 0, buf, size, id, + description); } EXPORT_SYMBOL_GPL(security_kernel_post_load_data); -- cgit v1.2.3 From 84594c9ecdca7ca595bc50e315093cb76921fd8e Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:31:09 +0100 Subject: ima: Move IMA-Appraisal to LSM infrastructure A few additional IMA hooks are needed to reset the cached appraisal status, causing the file's integrity to be re-evaluated on next access. Register these IMA-appraisal only functions separately from the rest of IMA functions, as appraisal is a separate feature not necessarily enabled in the kernel configuration. Reuse the same approach as for other IMA functions, move hardcoded calls from various places in the kernel to the LSM infrastructure. Declare the functions as static and register them as hook implementations in init_ima_appraise_lsm(), called by init_ima_lsm(). Also move the inline function ima_inode_remove_acl() from the public ima.h header to ima_appraise.c. Signed-off-by: Roberto Sassu Reviewed-by: Stefan Berger Reviewed-by: Mimi Zohar Reviewed-by: Casey Schaufler Acked-by: Christian Brauner Acked-by: Mimi Zohar Signed-off-by: Paul Moore --- security/integrity/ima/ima.h | 5 +++++ security/integrity/ima/ima_appraise.c | 38 ++++++++++++++++++++++++++--------- security/integrity/ima/ima_main.c | 1 + security/security.c | 13 ------------ 4 files changed, 35 insertions(+), 22 deletions(-) (limited to 'security') diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index c0412100023e..a27fc10f84f7 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -334,6 +334,7 @@ enum hash_algo ima_get_hash_algo(const struct evm_ima_xattr_data *xattr_value, int xattr_len); int ima_read_xattr(struct dentry *dentry, struct evm_ima_xattr_data **xattr_value, int xattr_len); +void __init init_ima_appraise_lsm(const struct lsm_id *lsmid); #else static inline int ima_check_blacklist(struct integrity_iint_cache *iint, @@ -385,6 +386,10 @@ static inline int ima_read_xattr(struct dentry *dentry, return 0; } +static inline void __init init_ima_appraise_lsm(const struct lsm_id *lsmid) +{ +} + #endif /* CONFIG_IMA_APPRAISE */ #ifdef CONFIG_IMA_APPRAISE_MODSIG diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 36abc84ba299..076451109637 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -636,8 +636,8 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file) * This function is called from notify_change(), which expects the caller * to lock the inode's i_mutex. */ -void ima_inode_post_setattr(struct mnt_idmap *idmap, - struct dentry *dentry, int ia_valid) +static void ima_inode_post_setattr(struct mnt_idmap *idmap, + struct dentry *dentry, int ia_valid) { struct inode *inode = d_backing_inode(dentry); struct integrity_iint_cache *iint; @@ -750,9 +750,9 @@ static int validate_hash_algo(struct dentry *dentry, return -EACCES; } -int ima_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, - const char *xattr_name, const void *xattr_value, - size_t xattr_value_len, int flags) +static int ima_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, + const char *xattr_name, const void *xattr_value, + size_t xattr_value_len, int flags) { const struct evm_ima_xattr_data *xvalue = xattr_value; int digsig = 0; @@ -781,8 +781,8 @@ int ima_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, return result; } -int ima_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, - const char *acl_name, struct posix_acl *kacl) +static int ima_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, + const char *acl_name, struct posix_acl *kacl) { if (evm_revalidate_status(acl_name)) ima_reset_appraise_flags(d_backing_inode(dentry), 0); @@ -790,8 +790,8 @@ int ima_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, return 0; } -int ima_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry, - const char *xattr_name) +static int ima_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry, + const char *xattr_name) { int result; @@ -803,3 +803,23 @@ int ima_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry, } return result; } + +static int ima_inode_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry, + const char *acl_name) +{ + return ima_inode_set_acl(idmap, dentry, acl_name, NULL); +} + +static struct security_hook_list ima_appraise_hooks[] __ro_after_init = { + LSM_HOOK_INIT(inode_post_setattr, ima_inode_post_setattr), + LSM_HOOK_INIT(inode_setxattr, ima_inode_setxattr), + LSM_HOOK_INIT(inode_set_acl, ima_inode_set_acl), + LSM_HOOK_INIT(inode_removexattr, ima_inode_removexattr), + LSM_HOOK_INIT(inode_remove_acl, ima_inode_remove_acl), +}; + +void __init init_ima_appraise_lsm(const struct lsm_id *lsmid) +{ + security_add_hooks(ima_appraise_hooks, ARRAY_SIZE(ima_appraise_hooks), + lsmid); +} diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index d0826e864c29..b8b8891a9379 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -1182,6 +1182,7 @@ static const struct lsm_id ima_lsmid = { static int __init init_ima_lsm(void) { security_add_hooks(ima_hooks, ARRAY_SIZE(ima_hooks), &ima_lsmid); + init_ima_appraise_lsm(&ima_lsmid); return 0; } diff --git a/security/security.c b/security/security.c index 8495890a5a37..bed659b53e59 100644 --- a/security/security.c +++ b/security/security.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -2308,9 +2307,6 @@ int security_inode_setxattr(struct mnt_idmap *idmap, if (ret == 1) ret = cap_inode_setxattr(dentry, name, value, size, flags); - if (ret) - return ret; - ret = ima_inode_setxattr(idmap, dentry, name, value, size, flags); if (ret) return ret; return evm_inode_setxattr(idmap, dentry, name, value, size, flags); @@ -2338,9 +2334,6 @@ int security_inode_set_acl(struct mnt_idmap *idmap, return 0; ret = call_int_hook(inode_set_acl, 0, idmap, dentry, acl_name, kacl); - if (ret) - return ret; - ret = ima_inode_set_acl(idmap, dentry, acl_name, kacl); if (ret) return ret; return evm_inode_set_acl(idmap, dentry, acl_name, kacl); @@ -2401,9 +2394,6 @@ int security_inode_remove_acl(struct mnt_idmap *idmap, if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; ret = call_int_hook(inode_remove_acl, 0, idmap, dentry, acl_name); - if (ret) - return ret; - ret = ima_inode_remove_acl(idmap, dentry, acl_name); if (ret) return ret; return evm_inode_remove_acl(idmap, dentry, acl_name); @@ -2503,9 +2493,6 @@ int security_inode_removexattr(struct mnt_idmap *idmap, ret = call_int_hook(inode_removexattr, 1, idmap, dentry, name); if (ret == 1) ret = cap_inode_removexattr(idmap, dentry, name); - if (ret) - return ret; - ret = ima_inode_removexattr(idmap, dentry, name); if (ret) return ret; return evm_inode_removexattr(idmap, dentry, name); -- cgit v1.2.3 From 9238311176115aac1b1a86e8e968c04ebec747a1 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:31:10 +0100 Subject: evm: Move to LSM infrastructure As for IMA, move hardcoded EVM function calls from various places in the kernel to the LSM infrastructure, by introducing a new LSM named 'evm' (last and always enabled like 'ima'). The order in the Makefile ensures that 'evm' hooks are executed after 'ima' ones. Make EVM functions as static (except for evm_inode_init_security(), which is exported), and register them as hook implementations in init_evm_lsm(). Also move the inline functions evm_inode_remove_acl(), evm_inode_post_remove_acl(), and evm_inode_post_set_acl() from the public evm.h header to evm_main.c. Unlike before (see commit to move IMA to the LSM infrastructure), evm_inode_post_setattr(), evm_inode_post_set_acl(), evm_inode_post_remove_acl(), and evm_inode_post_removexattr() are not executed for private inodes. Finally, add the LSM_ID_EVM case in lsm_list_modules_test.c Signed-off-by: Roberto Sassu Reviewed-by: Casey Schaufler Acked-by: Christian Brauner Reviewed-by: Stefan Berger Reviewed-by: Mimi Zohar Acked-by: Mimi Zohar Signed-off-by: Paul Moore --- security/integrity/evm/evm_main.c | 118 ++++++++++++++++++++++++++++++++------ security/security.c | 43 ++++---------- 2 files changed, 112 insertions(+), 49 deletions(-) (limited to 'security') diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index d35143179699..0a089af83a45 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -589,9 +589,9 @@ out: * userspace from writing HMAC value. Writing 'security.evm' requires * requires CAP_SYS_ADMIN privileges. */ -int evm_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, - const char *xattr_name, const void *xattr_value, - size_t xattr_value_len, int flags) +static int evm_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, + const char *xattr_name, const void *xattr_value, + size_t xattr_value_len, int flags) { const struct evm_ima_xattr_data *xattr_data = xattr_value; @@ -621,8 +621,8 @@ int evm_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, * Removing 'security.evm' requires CAP_SYS_ADMIN privileges and that * the current value is valid. */ -int evm_inode_removexattr(struct mnt_idmap *idmap, - struct dentry *dentry, const char *xattr_name) +static int evm_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry, + const char *xattr_name) { /* Policy permits modification of the protected xattrs even though * there's no HMAC key loaded @@ -672,9 +672,11 @@ static inline int evm_inode_set_acl_change(struct mnt_idmap *idmap, * Prevent modifying posix acls causing the EVM HMAC to be re-calculated * and 'security.evm' xattr updated, unless the existing 'security.evm' is * valid. + * + * Return: zero on success, -EPERM on failure. */ -int evm_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, - const char *acl_name, struct posix_acl *kacl) +static int evm_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, + const char *acl_name, struct posix_acl *kacl) { enum integrity_status evm_status; @@ -713,6 +715,24 @@ int evm_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, return -EPERM; } +/** + * evm_inode_remove_acl - Protect the EVM extended attribute from posix acls + * @idmap: idmap of the mount + * @dentry: pointer to the affected dentry + * @acl_name: name of the posix acl + * + * Prevent removing posix acls causing the EVM HMAC to be re-calculated + * and 'security.evm' xattr updated, unless the existing 'security.evm' is + * valid. + * + * Return: zero on success, -EPERM on failure. + */ +static int evm_inode_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry, + const char *acl_name) +{ + return evm_inode_set_acl(idmap, dentry, acl_name, NULL); +} + static void evm_reset_status(struct inode *inode) { struct integrity_iint_cache *iint; @@ -761,9 +781,11 @@ bool evm_revalidate_status(const char *xattr_name) * __vfs_setxattr_noperm(). The caller of which has taken the inode's * i_mutex lock. */ -void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, - const void *xattr_value, size_t xattr_value_len, - int flags) +static void evm_inode_post_setxattr(struct dentry *dentry, + const char *xattr_name, + const void *xattr_value, + size_t xattr_value_len, + int flags) { if (!evm_revalidate_status(xattr_name)) return; @@ -782,6 +804,21 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len); } +/** + * evm_inode_post_set_acl - Update the EVM extended attribute from posix acls + * @dentry: pointer to the affected dentry + * @acl_name: name of the posix acl + * @kacl: pointer to the posix acls + * + * Update the 'security.evm' xattr with the EVM HMAC re-calculated after setting + * posix acls. + */ +static void evm_inode_post_set_acl(struct dentry *dentry, const char *acl_name, + struct posix_acl *kacl) +{ + return evm_inode_post_setxattr(dentry, acl_name, NULL, 0, 0); +} + /** * evm_inode_post_removexattr - update 'security.evm' after removing the xattr * @dentry: pointer to the affected dentry @@ -792,7 +829,8 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, * No need to take the i_mutex lock here, as this function is called from * vfs_removexattr() which takes the i_mutex. */ -void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name) +static void evm_inode_post_removexattr(struct dentry *dentry, + const char *xattr_name) { if (!evm_revalidate_status(xattr_name)) return; @@ -808,6 +846,22 @@ void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name) evm_update_evmxattr(dentry, xattr_name, NULL, 0); } +/** + * evm_inode_post_remove_acl - Update the EVM extended attribute from posix acls + * @idmap: idmap of the mount + * @dentry: pointer to the affected dentry + * @acl_name: name of the posix acl + * + * Update the 'security.evm' xattr with the EVM HMAC re-calculated after + * removing posix acls. + */ +static inline void evm_inode_post_remove_acl(struct mnt_idmap *idmap, + struct dentry *dentry, + const char *acl_name) +{ + evm_inode_post_removexattr(dentry, acl_name); +} + static int evm_attr_change(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *attr) { @@ -831,8 +885,8 @@ static int evm_attr_change(struct mnt_idmap *idmap, * Permit update of file attributes when files have a valid EVM signature, * except in the case of them having an immutable portable signature. */ -int evm_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry, - struct iattr *attr) +static int evm_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + struct iattr *attr) { unsigned int ia_valid = attr->ia_valid; enum integrity_status evm_status; @@ -883,8 +937,8 @@ int evm_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry, * This function is called from notify_change(), which expects the caller * to lock the inode's i_mutex. */ -void evm_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry, - int ia_valid) +static void evm_inode_post_setattr(struct mnt_idmap *idmap, + struct dentry *dentry, int ia_valid) { if (!evm_revalidate_status(NULL)) return; @@ -901,7 +955,7 @@ void evm_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry, evm_update_evmxattr(dentry, NULL, NULL, 0); } -int evm_inode_copy_up_xattr(const char *name) +static int evm_inode_copy_up_xattr(const char *name) { if (strcmp(name, XATTR_NAME_EVM) == 0) return 1; /* Discard */ @@ -1004,4 +1058,36 @@ error: return error; } +static struct security_hook_list evm_hooks[] __ro_after_init = { + LSM_HOOK_INIT(inode_setattr, evm_inode_setattr), + LSM_HOOK_INIT(inode_post_setattr, evm_inode_post_setattr), + LSM_HOOK_INIT(inode_copy_up_xattr, evm_inode_copy_up_xattr), + LSM_HOOK_INIT(inode_setxattr, evm_inode_setxattr), + LSM_HOOK_INIT(inode_post_setxattr, evm_inode_post_setxattr), + LSM_HOOK_INIT(inode_set_acl, evm_inode_set_acl), + LSM_HOOK_INIT(inode_post_set_acl, evm_inode_post_set_acl), + LSM_HOOK_INIT(inode_remove_acl, evm_inode_remove_acl), + LSM_HOOK_INIT(inode_post_remove_acl, evm_inode_post_remove_acl), + LSM_HOOK_INIT(inode_removexattr, evm_inode_removexattr), + LSM_HOOK_INIT(inode_post_removexattr, evm_inode_post_removexattr), + LSM_HOOK_INIT(inode_init_security, evm_inode_init_security), +}; + +static const struct lsm_id evm_lsmid = { + .name = "evm", + .id = LSM_ID_EVM, +}; + +static int __init init_evm_lsm(void) +{ + security_add_hooks(evm_hooks, ARRAY_SIZE(evm_hooks), &evm_lsmid); + return 0; +} + +DEFINE_LSM(evm) = { + .name = "evm", + .init = init_evm_lsm, + .order = LSM_ORDER_LAST, +}; + late_initcall(init_evm); diff --git a/security/security.c b/security/security.c index bed659b53e59..59cb0e6cbae3 100644 --- a/security/security.c +++ b/security/security.c @@ -20,13 +20,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include #include @@ -50,7 +50,8 @@ (IS_ENABLED(CONFIG_SECURITY_LOCKDOWN_LSM) ? 1 : 0) + \ (IS_ENABLED(CONFIG_BPF_LSM) ? 1 : 0) + \ (IS_ENABLED(CONFIG_SECURITY_LANDLOCK) ? 1 : 0) + \ - (IS_ENABLED(CONFIG_IMA) ? 1 : 0)) + (IS_ENABLED(CONFIG_IMA) ? 1 : 0) + \ + (IS_ENABLED(CONFIG_EVM) ? 1 : 0)) /* * These are descriptions of the reasons that can be passed to the @@ -1740,10 +1741,6 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, if (!xattr_count) goto out; - ret = evm_inode_init_security(inode, dir, qstr, new_xattrs, - &xattr_count); - if (ret) - goto out; ret = initxattrs(inode, new_xattrs, fs_data); out: for (; xattr_count > 0; xattr_count--) @@ -2235,14 +2232,9 @@ int security_inode_permission(struct inode *inode, int mask) int security_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *attr) { - int ret; - if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - ret = call_int_hook(inode_setattr, 0, idmap, dentry, attr); - if (ret) - return ret; - return evm_inode_setattr(idmap, dentry, attr); + return call_int_hook(inode_setattr, 0, idmap, dentry, attr); } EXPORT_SYMBOL_GPL(security_inode_setattr); @@ -2307,9 +2299,7 @@ int security_inode_setxattr(struct mnt_idmap *idmap, if (ret == 1) ret = cap_inode_setxattr(dentry, name, value, size, flags); - if (ret) - return ret; - return evm_inode_setxattr(idmap, dentry, name, value, size, flags); + return ret; } /** @@ -2328,15 +2318,10 @@ int security_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name, struct posix_acl *kacl) { - int ret; - if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - ret = call_int_hook(inode_set_acl, 0, idmap, dentry, acl_name, - kacl); - if (ret) - return ret; - return evm_inode_set_acl(idmap, dentry, acl_name, kacl); + return call_int_hook(inode_set_acl, 0, idmap, dentry, acl_name, + kacl); } /** @@ -2389,14 +2374,9 @@ int security_inode_get_acl(struct mnt_idmap *idmap, int security_inode_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name) { - int ret; - if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - ret = call_int_hook(inode_remove_acl, 0, idmap, dentry, acl_name); - if (ret) - return ret; - return evm_inode_remove_acl(idmap, dentry, acl_name); + return call_int_hook(inode_remove_acl, 0, idmap, dentry, acl_name); } /** @@ -2432,7 +2412,6 @@ void security_inode_post_setxattr(struct dentry *dentry, const char *name, if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return; call_void_hook(inode_post_setxattr, dentry, name, value, size, flags); - evm_inode_post_setxattr(dentry, name, value, size, flags); } /** @@ -2493,9 +2472,7 @@ int security_inode_removexattr(struct mnt_idmap *idmap, ret = call_int_hook(inode_removexattr, 1, idmap, dentry, name); if (ret == 1) ret = cap_inode_removexattr(idmap, dentry, name); - if (ret) - return ret; - return evm_inode_removexattr(idmap, dentry, name); + return ret; } /** @@ -2699,7 +2676,7 @@ int security_inode_copy_up_xattr(const char *name) return rc; } - return evm_inode_copy_up_xattr(name); + return LSM_RET_DEFAULT(inode_copy_up_xattr); } EXPORT_SYMBOL(security_inode_copy_up_xattr); -- cgit v1.2.3 From 75a323e604fc77c50c7ef2af6f0eeef221637642 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:31:11 +0100 Subject: evm: Make it independent from 'integrity' LSM Define a new structure for EVM-specific metadata, called evm_iint_cache, and embed it in the inode security blob. Introduce evm_iint_inode() to retrieve metadata, and register evm_inode_alloc_security() for the inode_alloc_security LSM hook, to initialize the structure (before splitting metadata, this task was done by iint_init_always()). Keep the non-NULL checks after calling evm_iint_inode() except in evm_inode_alloc_security(), to take into account inodes for which security_inode_alloc() was not called. When using shared metadata, obtaining a NULL pointer from integrity_iint_find() meant that the file wasn't in the IMA policy. Now, because IMA and EVM use disjoint metadata, the EVM status has to be stored for every inode regardless of the IMA policy. Given that from now on EVM relies on its own metadata, remove the iint parameter from evm_verifyxattr(). Also, directly retrieve the iint in evm_verify_hmac(), called by both evm_verifyxattr() and evm_verify_current_integrity(), since now there is no performance penalty in retrieving EVM metadata (constant time). Replicate the management of the IMA_NEW_FILE flag, by introducing evm_post_path_mknod() and evm_file_release() to respectively set and clear the newly introduced flag EVM_NEW_FILE, at the same time IMA does. Like for IMA, select CONFIG_SECURITY_PATH when EVM is enabled, to ensure that files are marked as new. Unlike ima_post_path_mknod(), evm_post_path_mknod() cannot check if a file must be appraised. Thus, it marks all affected files. Also, it does not clear EVM_NEW_FILE depending on i_version, but that is not a problem because IMA_NEW_FILE is always cleared when set in ima_check_last_writer(). Move the EVM-specific flag EVM_IMMUTABLE_DIGSIG to security/integrity/evm/evm.h, since that definition is now unnecessary in the common integrity layer. Finally, switch to the LSM reservation mechanism for the EVM xattr, and consequently decrement by one the number of xattrs to allocate in security_inode_init_security(). Signed-off-by: Roberto Sassu Reviewed-by: Casey Schaufler Reviewed-by: Stefan Berger Reviewed-by: Mimi Zohar Acked-by: Mimi Zohar Signed-off-by: Paul Moore --- security/integrity/evm/Kconfig | 1 + security/integrity/evm/evm.h | 19 +++++++++ security/integrity/evm/evm_crypto.c | 4 +- security/integrity/evm/evm_main.c | 76 ++++++++++++++++++++++++++--------- security/integrity/ima/ima_appraise.c | 2 +- security/integrity/integrity.h | 1 - security/security.c | 4 +- 7 files changed, 81 insertions(+), 26 deletions(-) (limited to 'security') diff --git a/security/integrity/evm/Kconfig b/security/integrity/evm/Kconfig index fba9ee359bc9..861b3bacab82 100644 --- a/security/integrity/evm/Kconfig +++ b/security/integrity/evm/Kconfig @@ -6,6 +6,7 @@ config EVM select CRYPTO_HMAC select CRYPTO_SHA1 select CRYPTO_HASH_INFO + select SECURITY_PATH default n help EVM protects a file's security extended attributes against diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h index 53bd7fec93fa..eb1a2c343bd7 100644 --- a/security/integrity/evm/evm.h +++ b/security/integrity/evm/evm.h @@ -32,6 +32,25 @@ struct xattr_list { bool enabled; }; +#define EVM_NEW_FILE 0x00000001 +#define EVM_IMMUTABLE_DIGSIG 0x00000002 + +/* EVM integrity metadata associated with an inode */ +struct evm_iint_cache { + unsigned long flags; + enum integrity_status evm_status:4; +}; + +extern struct lsm_blob_sizes evm_blob_sizes; + +static inline struct evm_iint_cache *evm_iint_inode(const struct inode *inode) +{ + if (unlikely(!inode->i_security)) + return NULL; + + return inode->i_security + evm_blob_sizes.lbs_inode; +} + extern int evm_initialized; #define EVM_ATTR_FSUUID 0x0001 diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c index b1ffd4cc0b44..7552d49d0725 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c @@ -322,10 +322,10 @@ int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name, static int evm_is_immutable(struct dentry *dentry, struct inode *inode) { const struct evm_ima_xattr_data *xattr_data = NULL; - struct integrity_iint_cache *iint; + struct evm_iint_cache *iint; int rc = 0; - iint = integrity_iint_find(inode); + iint = evm_iint_inode(inode); if (iint && (iint->flags & EVM_IMMUTABLE_DIGSIG)) return 1; diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index 0a089af83a45..81dbade5b9b3 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -178,14 +178,14 @@ static int is_unsupported_fs(struct dentry *dentry) static enum integrity_status evm_verify_hmac(struct dentry *dentry, const char *xattr_name, char *xattr_value, - size_t xattr_value_len, - struct integrity_iint_cache *iint) + size_t xattr_value_len) { struct evm_ima_xattr_data *xattr_data = NULL; struct signature_v2_hdr *hdr; enum integrity_status evm_status = INTEGRITY_PASS; struct evm_digest digest; - struct inode *inode; + struct inode *inode = d_backing_inode(dentry); + struct evm_iint_cache *iint = evm_iint_inode(inode); int rc, xattr_len, evm_immutable = 0; if (iint && (iint->evm_status == INTEGRITY_PASS || @@ -254,8 +254,6 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry, (const char *)xattr_data, xattr_len, digest.digest, digest.hdr.length); if (!rc) { - inode = d_backing_inode(dentry); - if (xattr_data->type == EVM_XATTR_PORTABLE_DIGSIG) { if (iint) iint->flags |= EVM_IMMUTABLE_DIGSIG; @@ -403,7 +401,6 @@ int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer, * @xattr_name: requested xattr * @xattr_value: requested xattr value * @xattr_value_len: requested xattr value length - * @iint: inode integrity metadata * * Calculate the HMAC for the given dentry and verify it against the stored * security.evm xattr. For performance, use the xattr value and length @@ -416,8 +413,7 @@ int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer, */ enum integrity_status evm_verifyxattr(struct dentry *dentry, const char *xattr_name, - void *xattr_value, size_t xattr_value_len, - struct integrity_iint_cache *iint) + void *xattr_value, size_t xattr_value_len) { if (!evm_key_loaded() || !evm_protected_xattr(xattr_name)) return INTEGRITY_UNKNOWN; @@ -425,13 +421,8 @@ enum integrity_status evm_verifyxattr(struct dentry *dentry, if (is_unsupported_fs(dentry)) return INTEGRITY_UNKNOWN; - if (!iint) { - iint = integrity_iint_find(d_backing_inode(dentry)); - if (!iint) - return INTEGRITY_UNKNOWN; - } return evm_verify_hmac(dentry, xattr_name, xattr_value, - xattr_value_len, iint); + xattr_value_len); } EXPORT_SYMBOL_GPL(evm_verifyxattr); @@ -448,7 +439,7 @@ static enum integrity_status evm_verify_current_integrity(struct dentry *dentry) if (!evm_key_loaded() || !S_ISREG(inode->i_mode) || evm_fixmode) return INTEGRITY_PASS; - return evm_verify_hmac(dentry, NULL, NULL, 0, NULL); + return evm_verify_hmac(dentry, NULL, NULL, 0); } /* @@ -526,14 +517,14 @@ static int evm_protect_xattr(struct mnt_idmap *idmap, evm_status = evm_verify_current_integrity(dentry); if (evm_status == INTEGRITY_NOXATTRS) { - struct integrity_iint_cache *iint; + struct evm_iint_cache *iint; /* Exception if the HMAC is not going to be calculated. */ if (evm_hmac_disabled()) return 0; - iint = integrity_iint_find(d_backing_inode(dentry)); - if (iint && (iint->flags & IMA_NEW_FILE)) + iint = evm_iint_inode(d_backing_inode(dentry)); + if (iint && (iint->flags & EVM_NEW_FILE)) return 0; /* exception for pseudo filesystems */ @@ -735,9 +726,9 @@ static int evm_inode_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry, static void evm_reset_status(struct inode *inode) { - struct integrity_iint_cache *iint; + struct evm_iint_cache *iint; - iint = integrity_iint_find(inode); + iint = evm_iint_inode(inode); if (iint) iint->evm_status = INTEGRITY_UNKNOWN; } @@ -1019,6 +1010,42 @@ out: } EXPORT_SYMBOL_GPL(evm_inode_init_security); +static int evm_inode_alloc_security(struct inode *inode) +{ + struct evm_iint_cache *iint = evm_iint_inode(inode); + + /* Called by security_inode_alloc(), it cannot be NULL. */ + iint->flags = 0UL; + iint->evm_status = INTEGRITY_UNKNOWN; + + return 0; +} + +static void evm_file_release(struct file *file) +{ + struct inode *inode = file_inode(file); + struct evm_iint_cache *iint = evm_iint_inode(inode); + fmode_t mode = file->f_mode; + + if (!S_ISREG(inode->i_mode) || !(mode & FMODE_WRITE)) + return; + + if (iint && atomic_read(&inode->i_writecount) == 1) + iint->flags &= ~EVM_NEW_FILE; +} + +static void evm_post_path_mknod(struct mnt_idmap *idmap, struct dentry *dentry) +{ + struct inode *inode = d_backing_inode(dentry); + struct evm_iint_cache *iint = evm_iint_inode(inode); + + if (!S_ISREG(inode->i_mode)) + return; + + if (iint) + iint->flags |= EVM_NEW_FILE; +} + #ifdef CONFIG_EVM_LOAD_X509 void __init evm_load_x509(void) { @@ -1071,6 +1098,9 @@ static struct security_hook_list evm_hooks[] __ro_after_init = { LSM_HOOK_INIT(inode_removexattr, evm_inode_removexattr), LSM_HOOK_INIT(inode_post_removexattr, evm_inode_post_removexattr), LSM_HOOK_INIT(inode_init_security, evm_inode_init_security), + LSM_HOOK_INIT(inode_alloc_security, evm_inode_alloc_security), + LSM_HOOK_INIT(file_release, evm_file_release), + LSM_HOOK_INIT(path_post_mknod, evm_post_path_mknod), }; static const struct lsm_id evm_lsmid = { @@ -1084,10 +1114,16 @@ static int __init init_evm_lsm(void) return 0; } +struct lsm_blob_sizes evm_blob_sizes __ro_after_init = { + .lbs_inode = sizeof(struct evm_iint_cache), + .lbs_xattr_count = 1, +}; + DEFINE_LSM(evm) = { .name = "evm", .init = init_evm_lsm, .order = LSM_ORDER_LAST, + .blobs = &evm_blob_sizes, }; late_initcall(init_evm); diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 076451109637..1dd6ee72a20a 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -520,7 +520,7 @@ int ima_appraise_measurement(enum ima_hooks func, } status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, - rc < 0 ? 0 : rc, iint); + rc < 0 ? 0 : rc); switch (status) { case INTEGRITY_PASS: case INTEGRITY_PASS_IMMUTABLE: diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 59eaddd84434..7a97c269a072 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -37,7 +37,6 @@ #define IMA_DIGSIG_REQUIRED 0x01000000 #define IMA_PERMIT_DIRECTIO 0x02000000 #define IMA_NEW_FILE 0x04000000 -#define EVM_IMMUTABLE_DIGSIG 0x08000000 #define IMA_FAIL_UNVERIFIABLE_SIGS 0x10000000 #define IMA_MODSIG_ALLOWED 0x20000000 #define IMA_CHECK_BLACKLIST 0x40000000 diff --git a/security/security.c b/security/security.c index 59cb0e6cbae3..e08c1aa82edf 100644 --- a/security/security.c +++ b/security/security.c @@ -1716,8 +1716,8 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, return 0; if (initxattrs) { - /* Allocate +1 for EVM and +1 as terminator. */ - new_xattrs = kcalloc(blob_sizes.lbs_xattr_count + 2, + /* Allocate +1 as terminator. */ + new_xattrs = kcalloc(blob_sizes.lbs_xattr_count + 1, sizeof(*new_xattrs), GFP_NOFS); if (!new_xattrs) return -ENOMEM; -- cgit v1.2.3 From 4de2f084fbff41113d9adec3c9e15ab12bf05e21 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:31:12 +0100 Subject: ima: Make it independent from 'integrity' LSM Make the 'ima' LSM independent from the 'integrity' LSM by introducing IMA own integrity metadata (ima_iint_cache structure, with IMA-specific fields from the integrity_iint_cache structure), and by managing it directly from the 'ima' LSM. Create ima_iint.c and introduce the same integrity metadata management functions found in iint.c (renamed with ima_). However, instead of putting metadata in an rbtree, reserve space from IMA in the inode security blob for a pointer, and introduce the ima_inode_set_iint()/ima_inode_get_iint() primitives to store/retrieve that pointer. This improves search time from logarithmic to constant. Consequently, don't include the inode pointer as field in the ima_iint_cache structure, since the association with the inode is clear. Since the inode field is missing in ima_iint_cache, pass the extra inode parameter to ima_get_verity_digest(). Prefer storing the pointer instead of the entire ima_iint_cache structure, to avoid too much memory pressure. Use the same mechanism as before, a cache named ima_iint_cache (renamed from iint_cache), to quickly allocate a new ima_iint_cache structure when requested by the IMA policy. Create the new ima_iint_cache in ima_iintcache_init(), called by init_ima_lsm(), during the initialization of the 'ima' LSM. And, register ima_inode_free_security() to free the ima_iint_cache structure, if exists. Replace integrity_iint_cache with ima_iint_cache in various places of the IMA code. Also, replace integrity_inode_get() and integrity_iint_find(), respectively with ima_inode_get() and ima_iint_find(). Finally, move the remaining IMA-specific flags to security/integrity/ima/ima.h, since they are now unnecessary in the common integrity layer. Signed-off-by: Roberto Sassu Reviewed-by: Casey Schaufler Reviewed-by: Stefan Berger Reviewed-by: Mimi Zohar Acked-by: Mimi Zohar Signed-off-by: Paul Moore --- security/integrity/ima/Makefile | 2 +- security/integrity/ima/ima.h | 137 +++++++++++++++++++++++++++----- security/integrity/ima/ima_api.c | 23 +++--- security/integrity/ima/ima_appraise.c | 27 +++---- security/integrity/ima/ima_iint.c | 142 ++++++++++++++++++++++++++++++++++ security/integrity/ima/ima_init.c | 2 +- security/integrity/ima/ima_main.c | 36 +++++---- security/integrity/ima/ima_policy.c | 2 +- security/integrity/integrity.h | 53 ------------- 9 files changed, 308 insertions(+), 116 deletions(-) create mode 100644 security/integrity/ima/ima_iint.c (limited to 'security') diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile index 2499f2485c04..b376d38b4ee6 100644 --- a/security/integrity/ima/Makefile +++ b/security/integrity/ima/Makefile @@ -4,7 +4,7 @@ # Measurement Architecture(IMA). # -obj-$(CONFIG_IMA) += ima.o +obj-$(CONFIG_IMA) += ima.o ima_iint.o ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \ ima_policy.o ima_template.o ima_template_lib.o diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index a27fc10f84f7..11d7c0332207 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -60,7 +60,7 @@ extern const char boot_aggregate_name[]; /* IMA event related data */ struct ima_event_data { - struct integrity_iint_cache *iint; + struct ima_iint_cache *iint; struct file *file; const unsigned char *filename; struct evm_ima_xattr_data *xattr_value; @@ -119,6 +119,107 @@ struct ima_kexec_hdr { u64 count; }; +/* IMA iint action cache flags */ +#define IMA_MEASURE 0x00000001 +#define IMA_MEASURED 0x00000002 +#define IMA_APPRAISE 0x00000004 +#define IMA_APPRAISED 0x00000008 +/*#define IMA_COLLECT 0x00000010 do not use this flag */ +#define IMA_COLLECTED 0x00000020 +#define IMA_AUDIT 0x00000040 +#define IMA_AUDITED 0x00000080 +#define IMA_HASH 0x00000100 +#define IMA_HASHED 0x00000200 + +/* IMA iint policy rule cache flags */ +#define IMA_NONACTION_FLAGS 0xff000000 +#define IMA_DIGSIG_REQUIRED 0x01000000 +#define IMA_PERMIT_DIRECTIO 0x02000000 +#define IMA_NEW_FILE 0x04000000 +#define IMA_FAIL_UNVERIFIABLE_SIGS 0x10000000 +#define IMA_MODSIG_ALLOWED 0x20000000 +#define IMA_CHECK_BLACKLIST 0x40000000 +#define IMA_VERITY_REQUIRED 0x80000000 + +#define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \ + IMA_HASH | IMA_APPRAISE_SUBMASK) +#define IMA_DONE_MASK (IMA_MEASURED | IMA_APPRAISED | IMA_AUDITED | \ + IMA_HASHED | IMA_COLLECTED | \ + IMA_APPRAISED_SUBMASK) + +/* IMA iint subaction appraise cache flags */ +#define IMA_FILE_APPRAISE 0x00001000 +#define IMA_FILE_APPRAISED 0x00002000 +#define IMA_MMAP_APPRAISE 0x00004000 +#define IMA_MMAP_APPRAISED 0x00008000 +#define IMA_BPRM_APPRAISE 0x00010000 +#define IMA_BPRM_APPRAISED 0x00020000 +#define IMA_READ_APPRAISE 0x00040000 +#define IMA_READ_APPRAISED 0x00080000 +#define IMA_CREDS_APPRAISE 0x00100000 +#define IMA_CREDS_APPRAISED 0x00200000 +#define IMA_APPRAISE_SUBMASK (IMA_FILE_APPRAISE | IMA_MMAP_APPRAISE | \ + IMA_BPRM_APPRAISE | IMA_READ_APPRAISE | \ + IMA_CREDS_APPRAISE) +#define IMA_APPRAISED_SUBMASK (IMA_FILE_APPRAISED | IMA_MMAP_APPRAISED | \ + IMA_BPRM_APPRAISED | IMA_READ_APPRAISED | \ + IMA_CREDS_APPRAISED) + +/* IMA iint cache atomic_flags */ +#define IMA_CHANGE_XATTR 0 +#define IMA_UPDATE_XATTR 1 +#define IMA_CHANGE_ATTR 2 +#define IMA_DIGSIG 3 +#define IMA_MUST_MEASURE 4 + +/* IMA integrity metadata associated with an inode */ +struct ima_iint_cache { + struct mutex mutex; /* protects: version, flags, digest */ + u64 version; /* track inode changes */ + unsigned long flags; + unsigned long measured_pcrs; + unsigned long atomic_flags; + unsigned long real_ino; + dev_t real_dev; + enum integrity_status ima_file_status:4; + enum integrity_status ima_mmap_status:4; + enum integrity_status ima_bprm_status:4; + enum integrity_status ima_read_status:4; + enum integrity_status ima_creds_status:4; + struct ima_digest_data *ima_hash; +}; + +extern struct lsm_blob_sizes ima_blob_sizes; + +static inline struct ima_iint_cache * +ima_inode_get_iint(const struct inode *inode) +{ + struct ima_iint_cache **iint_sec; + + if (unlikely(!inode->i_security)) + return NULL; + + iint_sec = inode->i_security + ima_blob_sizes.lbs_inode; + return *iint_sec; +} + +static inline void ima_inode_set_iint(const struct inode *inode, + struct ima_iint_cache *iint) +{ + struct ima_iint_cache **iint_sec; + + if (unlikely(!inode->i_security)) + return; + + iint_sec = inode->i_security + ima_blob_sizes.lbs_inode; + *iint_sec = iint; +} + +struct ima_iint_cache *ima_iint_find(struct inode *inode); +struct ima_iint_cache *ima_inode_get(struct inode *inode); +void ima_inode_free(struct inode *inode); +void __init ima_iintcache_init(void); + extern const int read_idmap[]; #ifdef CONFIG_HAVE_IMA_KEXEC @@ -152,8 +253,8 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data, struct ima_template_entry *entry); int ima_calc_boot_aggregate(struct ima_digest_data *hash); void ima_add_violation(struct file *file, const unsigned char *filename, - struct integrity_iint_cache *iint, - const char *op, const char *cause); + struct ima_iint_cache *iint, const char *op, + const char *cause); int ima_init_crypto(void); void ima_putc(struct seq_file *m, void *data, int datalen); void ima_print_digest(struct seq_file *m, u8 *digest, u32 size); @@ -267,10 +368,10 @@ int ima_get_action(struct mnt_idmap *idmap, struct inode *inode, struct ima_template_desc **template_desc, const char *func_data, unsigned int *allowed_algos); int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func); -int ima_collect_measurement(struct integrity_iint_cache *iint, - struct file *file, void *buf, loff_t size, - enum hash_algo algo, struct modsig *modsig); -void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, +int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file, + void *buf, loff_t size, enum hash_algo algo, + struct modsig *modsig); +void ima_store_measurement(struct ima_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, int xattr_len, const struct modsig *modsig, int pcr, @@ -280,7 +381,7 @@ int process_buffer_measurement(struct mnt_idmap *idmap, const char *eventname, enum ima_hooks func, int pcr, const char *func_data, bool buf_hash, u8 *digest, size_t digest_len); -void ima_audit_measurement(struct integrity_iint_cache *iint, +void ima_audit_measurement(struct ima_iint_cache *iint, const unsigned char *filename); int ima_alloc_init_template(struct ima_event_data *event_data, struct ima_template_entry **entry, @@ -318,17 +419,16 @@ int ima_policy_show(struct seq_file *m, void *v); #define IMA_APPRAISE_KEXEC 0x40 #ifdef CONFIG_IMA_APPRAISE -int ima_check_blacklist(struct integrity_iint_cache *iint, +int ima_check_blacklist(struct ima_iint_cache *iint, const struct modsig *modsig, int pcr); -int ima_appraise_measurement(enum ima_hooks func, - struct integrity_iint_cache *iint, +int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, int xattr_len, const struct modsig *modsig); int ima_must_appraise(struct mnt_idmap *idmap, struct inode *inode, int mask, enum ima_hooks func); -void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file); -enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, +void ima_update_xattr(struct ima_iint_cache *iint, struct file *file); +enum integrity_status ima_get_cache_status(struct ima_iint_cache *iint, enum ima_hooks func); enum hash_algo ima_get_hash_algo(const struct evm_ima_xattr_data *xattr_value, int xattr_len); @@ -337,14 +437,14 @@ int ima_read_xattr(struct dentry *dentry, void __init init_ima_appraise_lsm(const struct lsm_id *lsmid); #else -static inline int ima_check_blacklist(struct integrity_iint_cache *iint, +static inline int ima_check_blacklist(struct ima_iint_cache *iint, const struct modsig *modsig, int pcr) { return 0; } static inline int ima_appraise_measurement(enum ima_hooks func, - struct integrity_iint_cache *iint, + struct ima_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, @@ -361,14 +461,13 @@ static inline int ima_must_appraise(struct mnt_idmap *idmap, return 0; } -static inline void ima_update_xattr(struct integrity_iint_cache *iint, +static inline void ima_update_xattr(struct ima_iint_cache *iint, struct file *file) { } -static inline enum integrity_status ima_get_cache_status(struct integrity_iint_cache - *iint, - enum ima_hooks func) +static inline enum integrity_status +ima_get_cache_status(struct ima_iint_cache *iint, enum ima_hooks func) { return INTEGRITY_UNKNOWN; } diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 597ea0c4d72f..b37d043d5748 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -131,8 +131,8 @@ int ima_store_template(struct ima_template_entry *entry, * value is invalidated. */ void ima_add_violation(struct file *file, const unsigned char *filename, - struct integrity_iint_cache *iint, - const char *op, const char *cause) + struct ima_iint_cache *iint, const char *op, + const char *cause) { struct ima_template_entry *entry; struct inode *inode = file_inode(file); @@ -201,7 +201,8 @@ int ima_get_action(struct mnt_idmap *idmap, struct inode *inode, allowed_algos); } -static bool ima_get_verity_digest(struct integrity_iint_cache *iint, +static bool ima_get_verity_digest(struct ima_iint_cache *iint, + struct inode *inode, struct ima_max_digest_data *hash) { enum hash_algo alg; @@ -211,7 +212,7 @@ static bool ima_get_verity_digest(struct integrity_iint_cache *iint, * On failure, 'measure' policy rules will result in a file data * hash containing 0's. */ - digest_len = fsverity_get_digest(iint->inode, hash->digest, NULL, &alg); + digest_len = fsverity_get_digest(inode, hash->digest, NULL, &alg); if (digest_len == 0) return false; @@ -237,9 +238,9 @@ static bool ima_get_verity_digest(struct integrity_iint_cache *iint, * * Return 0 on success, error code otherwise */ -int ima_collect_measurement(struct integrity_iint_cache *iint, - struct file *file, void *buf, loff_t size, - enum hash_algo algo, struct modsig *modsig) +int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file, + void *buf, loff_t size, enum hash_algo algo, + struct modsig *modsig) { const char *audit_cause = "failed"; struct inode *inode = file_inode(file); @@ -280,7 +281,7 @@ int ima_collect_measurement(struct integrity_iint_cache *iint, memset(&hash.digest, 0, sizeof(hash.digest)); if (iint->flags & IMA_VERITY_REQUIRED) { - if (!ima_get_verity_digest(iint, &hash)) { + if (!ima_get_verity_digest(iint, inode, &hash)) { audit_cause = "no-verity-digest"; result = -ENODATA; } @@ -338,8 +339,8 @@ out: * * Must be called with iint->mutex held. */ -void ima_store_measurement(struct integrity_iint_cache *iint, - struct file *file, const unsigned char *filename, +void ima_store_measurement(struct ima_iint_cache *iint, struct file *file, + const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, int xattr_len, const struct modsig *modsig, int pcr, struct ima_template_desc *template_desc) @@ -382,7 +383,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint, ima_free_template_entry(entry); } -void ima_audit_measurement(struct integrity_iint_cache *iint, +void ima_audit_measurement(struct ima_iint_cache *iint, const unsigned char *filename) { struct audit_buffer *ab; diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 1dd6ee72a20a..3497741caea9 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -84,8 +84,7 @@ int ima_must_appraise(struct mnt_idmap *idmap, struct inode *inode, NULL, NULL, NULL); } -static int ima_fix_xattr(struct dentry *dentry, - struct integrity_iint_cache *iint) +static int ima_fix_xattr(struct dentry *dentry, struct ima_iint_cache *iint) { int rc, offset; u8 algo = iint->ima_hash->algo; @@ -106,7 +105,7 @@ static int ima_fix_xattr(struct dentry *dentry, } /* Return specific func appraised cached result */ -enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, +enum integrity_status ima_get_cache_status(struct ima_iint_cache *iint, enum ima_hooks func) { switch (func) { @@ -126,7 +125,7 @@ enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, } } -static void ima_set_cache_status(struct integrity_iint_cache *iint, +static void ima_set_cache_status(struct ima_iint_cache *iint, enum ima_hooks func, enum integrity_status status) { @@ -152,8 +151,7 @@ static void ima_set_cache_status(struct integrity_iint_cache *iint, } } -static void ima_cache_flags(struct integrity_iint_cache *iint, - enum ima_hooks func) +static void ima_cache_flags(struct ima_iint_cache *iint, enum ima_hooks func) { switch (func) { case MMAP_CHECK: @@ -276,7 +274,7 @@ static int calc_file_id_hash(enum evm_ima_xattr_type type, * * Return 0 on success, error code otherwise. */ -static int xattr_verify(enum ima_hooks func, struct integrity_iint_cache *iint, +static int xattr_verify(enum ima_hooks func, struct ima_iint_cache *iint, struct evm_ima_xattr_data *xattr_value, int xattr_len, enum integrity_status *status, const char **cause) { @@ -443,7 +441,7 @@ static int modsig_verify(enum ima_hooks func, const struct modsig *modsig, * * Returns -EPERM if the hash is blacklisted. */ -int ima_check_blacklist(struct integrity_iint_cache *iint, +int ima_check_blacklist(struct ima_iint_cache *iint, const struct modsig *modsig, int pcr) { enum hash_algo hash_algo; @@ -477,8 +475,7 @@ int ima_check_blacklist(struct integrity_iint_cache *iint, * * Return 0 on success, error code otherwise */ -int ima_appraise_measurement(enum ima_hooks func, - struct integrity_iint_cache *iint, +int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, int xattr_len, const struct modsig *modsig) @@ -603,7 +600,7 @@ out: /* * ima_update_xattr - update 'security.ima' hash value */ -void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file) +void ima_update_xattr(struct ima_iint_cache *iint, struct file *file) { struct dentry *dentry = file_dentry(file); int rc = 0; @@ -640,7 +637,7 @@ static void ima_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry, int ia_valid) { struct inode *inode = d_backing_inode(dentry); - struct integrity_iint_cache *iint; + struct ima_iint_cache *iint; int action; if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode) @@ -648,7 +645,7 @@ static void ima_inode_post_setattr(struct mnt_idmap *idmap, return; action = ima_must_appraise(idmap, inode, MAY_ACCESS, POST_SETATTR); - iint = integrity_iint_find(inode); + iint = ima_iint_find(inode); if (iint) { set_bit(IMA_CHANGE_ATTR, &iint->atomic_flags); if (!action) @@ -674,12 +671,12 @@ static int ima_protect_xattr(struct dentry *dentry, const char *xattr_name, static void ima_reset_appraise_flags(struct inode *inode, int digsig) { - struct integrity_iint_cache *iint; + struct ima_iint_cache *iint; if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)) return; - iint = integrity_iint_find(inode); + iint = ima_iint_find(inode); if (!iint) return; iint->measured_pcrs = 0; diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c new file mode 100644 index 000000000000..e7c9c216c1c6 --- /dev/null +++ b/security/integrity/ima/ima_iint.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2008 IBM Corporation + * + * Authors: + * Mimi Zohar + * + * File: ima_iint.c + * - implements the IMA hook: ima_inode_free + * - cache integrity information in the inode security blob + */ +#include + +#include "ima.h" + +static struct kmem_cache *ima_iint_cache __ro_after_init; + +/** + * ima_iint_find - Return the iint associated with an inode + * @inode: Pointer to the inode + * + * Return the IMA integrity information (iint) associated with an inode, if the + * inode was processed by IMA. + * + * Return: Found iint or NULL. + */ +struct ima_iint_cache *ima_iint_find(struct inode *inode) +{ + if (!IS_IMA(inode)) + return NULL; + + return ima_inode_get_iint(inode); +} + +#define IMA_MAX_NESTING (FILESYSTEM_MAX_STACK_DEPTH + 1) + +/* + * It is not clear that IMA should be nested at all, but as long is it measures + * files both on overlayfs and on underlying fs, we need to annotate the iint + * mutex to avoid lockdep false positives related to IMA + overlayfs. + * See ovl_lockdep_annotate_inode_mutex_key() for more details. + */ +static inline void ima_iint_lockdep_annotate(struct ima_iint_cache *iint, + struct inode *inode) +{ +#ifdef CONFIG_LOCKDEP + static struct lock_class_key ima_iint_mutex_key[IMA_MAX_NESTING]; + + int depth = inode->i_sb->s_stack_depth; + + if (WARN_ON_ONCE(depth < 0 || depth >= IMA_MAX_NESTING)) + depth = 0; + + lockdep_set_class(&iint->mutex, &ima_iint_mutex_key[depth]); +#endif +} + +static void ima_iint_init_always(struct ima_iint_cache *iint, + struct inode *inode) +{ + iint->ima_hash = NULL; + iint->version = 0; + iint->flags = 0UL; + iint->atomic_flags = 0UL; + iint->ima_file_status = INTEGRITY_UNKNOWN; + iint->ima_mmap_status = INTEGRITY_UNKNOWN; + iint->ima_bprm_status = INTEGRITY_UNKNOWN; + iint->ima_read_status = INTEGRITY_UNKNOWN; + iint->ima_creds_status = INTEGRITY_UNKNOWN; + iint->measured_pcrs = 0; + mutex_init(&iint->mutex); + ima_iint_lockdep_annotate(iint, inode); +} + +static void ima_iint_free(struct ima_iint_cache *iint) +{ + kfree(iint->ima_hash); + mutex_destroy(&iint->mutex); + kmem_cache_free(ima_iint_cache, iint); +} + +/** + * ima_inode_get - Find or allocate an iint associated with an inode + * @inode: Pointer to the inode + * + * Find an iint associated with an inode, and allocate a new one if not found. + * Caller must lock i_mutex. + * + * Return: An iint on success, NULL on error. + */ +struct ima_iint_cache *ima_inode_get(struct inode *inode) +{ + struct ima_iint_cache *iint; + + iint = ima_iint_find(inode); + if (iint) + return iint; + + iint = kmem_cache_alloc(ima_iint_cache, GFP_NOFS); + if (!iint) + return NULL; + + ima_iint_init_always(iint, inode); + + inode->i_flags |= S_IMA; + ima_inode_set_iint(inode, iint); + + return iint; +} + +/** + * ima_inode_free - Called on inode free + * @inode: Pointer to the inode + * + * Free the iint associated with an inode. + */ +void ima_inode_free(struct inode *inode) +{ + struct ima_iint_cache *iint; + + if (!IS_IMA(inode)) + return; + + iint = ima_iint_find(inode); + ima_inode_set_iint(inode, NULL); + + ima_iint_free(iint); +} + +static void ima_iint_init_once(void *foo) +{ + struct ima_iint_cache *iint = (struct ima_iint_cache *)foo; + + memset(iint, 0, sizeof(*iint)); +} + +void __init ima_iintcache_init(void) +{ + ima_iint_cache = + kmem_cache_create("ima_iint_cache", sizeof(struct ima_iint_cache), + 0, SLAB_PANIC, ima_iint_init_once); +} diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 63979aefc95f..393f5c7912d5 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -44,7 +44,7 @@ static int __init ima_add_boot_aggregate(void) static const char op[] = "add_boot_aggregate"; const char *audit_cause = "ENOMEM"; struct ima_template_entry *entry; - struct integrity_iint_cache tmp_iint, *iint = &tmp_iint; + struct ima_iint_cache tmp_iint, *iint = &tmp_iint; struct ima_event_data event_data = { .iint = iint, .filename = boot_aggregate_name }; struct ima_max_digest_data hash; diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index b8b8891a9379..c84e8c55333d 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -114,7 +114,7 @@ static int mmap_violation_check(enum ima_hooks func, struct file *file, * */ static void ima_rdwr_violation_check(struct file *file, - struct integrity_iint_cache *iint, + struct ima_iint_cache *iint, int must_measure, char **pathbuf, const char **pathname, @@ -127,7 +127,7 @@ static void ima_rdwr_violation_check(struct file *file, if (mode & FMODE_WRITE) { if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) { if (!iint) - iint = integrity_iint_find(inode); + iint = ima_iint_find(inode); /* IMA_MEASURE is set from reader side */ if (iint && test_bit(IMA_MUST_MEASURE, &iint->atomic_flags)) @@ -153,7 +153,7 @@ static void ima_rdwr_violation_check(struct file *file, "invalid_pcr", "open_writers"); } -static void ima_check_last_writer(struct integrity_iint_cache *iint, +static void ima_check_last_writer(struct ima_iint_cache *iint, struct inode *inode, struct file *file) { fmode_t mode = file->f_mode; @@ -192,12 +192,12 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint, static void ima_file_free(struct file *file) { struct inode *inode = file_inode(file); - struct integrity_iint_cache *iint; + struct ima_iint_cache *iint; if (!ima_policy_flag || !S_ISREG(inode->i_mode)) return; - iint = integrity_iint_find(inode); + iint = ima_iint_find(inode); if (!iint) return; @@ -209,7 +209,7 @@ static int process_measurement(struct file *file, const struct cred *cred, enum ima_hooks func) { struct inode *backing_inode, *inode = file_inode(file); - struct integrity_iint_cache *iint = NULL; + struct ima_iint_cache *iint = NULL; struct ima_template_desc *template_desc = NULL; char *pathbuf = NULL; char filename[NAME_MAX]; @@ -248,7 +248,7 @@ static int process_measurement(struct file *file, const struct cred *cred, inode_lock(inode); if (action) { - iint = integrity_inode_get(inode); + iint = ima_inode_get(inode); if (!iint) rc = -ENOMEM; } @@ -564,11 +564,11 @@ static int ima_file_check(struct file *file, int mask) static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf, size_t buf_size) { - struct integrity_iint_cache *iint = NULL, tmp_iint; + struct ima_iint_cache *iint = NULL, tmp_iint; int rc, hash_algo; if (ima_policy_flag) { - iint = integrity_iint_find(inode); + iint = ima_iint_find(inode); if (iint) mutex_lock(&iint->mutex); } @@ -578,7 +578,6 @@ static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf, mutex_unlock(&iint->mutex); memset(&tmp_iint, 0, sizeof(tmp_iint)); - tmp_iint.inode = inode; mutex_init(&tmp_iint.mutex); rc = ima_collect_measurement(&tmp_iint, file, NULL, 0, @@ -688,7 +687,7 @@ static void ima_post_create_tmpfile(struct mnt_idmap *idmap, struct inode *inode) { - struct integrity_iint_cache *iint; + struct ima_iint_cache *iint; int must_appraise; if (!ima_policy_flag || !S_ISREG(inode->i_mode)) @@ -700,7 +699,7 @@ static void ima_post_create_tmpfile(struct mnt_idmap *idmap, return; /* Nothing to do if we can't allocate memory */ - iint = integrity_inode_get(inode); + iint = ima_inode_get(inode); if (!iint) return; @@ -719,7 +718,7 @@ static void ima_post_create_tmpfile(struct mnt_idmap *idmap, */ static void ima_post_path_mknod(struct mnt_idmap *idmap, struct dentry *dentry) { - struct integrity_iint_cache *iint; + struct ima_iint_cache *iint; struct inode *inode = dentry->d_inode; int must_appraise; @@ -732,7 +731,7 @@ static void ima_post_path_mknod(struct mnt_idmap *idmap, struct dentry *dentry) return; /* Nothing to do if we can't allocate memory */ - iint = integrity_inode_get(inode); + iint = ima_inode_get(inode); if (!iint) return; @@ -935,7 +934,7 @@ int process_buffer_measurement(struct mnt_idmap *idmap, int ret = 0; const char *audit_cause = "ENOMEM"; struct ima_template_entry *entry = NULL; - struct integrity_iint_cache iint = {}; + struct ima_iint_cache iint = {}; struct ima_event_data event_data = {.iint = &iint, .filename = eventname, .buf = buf, @@ -1172,6 +1171,7 @@ static struct security_hook_list ima_hooks[] __ro_after_init = { #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS LSM_HOOK_INIT(kernel_module_request, ima_kernel_module_request), #endif + LSM_HOOK_INIT(inode_free_security, ima_inode_free), }; static const struct lsm_id ima_lsmid = { @@ -1181,15 +1181,21 @@ static const struct lsm_id ima_lsmid = { static int __init init_ima_lsm(void) { + ima_iintcache_init(); security_add_hooks(ima_hooks, ARRAY_SIZE(ima_hooks), &ima_lsmid); init_ima_appraise_lsm(&ima_lsmid); return 0; } +struct lsm_blob_sizes ima_blob_sizes __ro_after_init = { + .lbs_inode = sizeof(struct ima_iint_cache *), +}; + DEFINE_LSM(ima) = { .name = "ima", .init = init_ima_lsm, .order = LSM_ORDER_LAST, + .blobs = &ima_blob_sizes, }; late_initcall(init_ima); /* Start IMA after the TPM is available */ diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index f69062617754..c0556907c2e6 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -49,7 +49,7 @@ #define DONT_HASH 0x0200 #define INVALID_PCR(a) (((a) < 0) || \ - (a) >= (sizeof_field(struct integrity_iint_cache, measured_pcrs) * 8)) + (a) >= (sizeof_field(struct ima_iint_cache, measured_pcrs) * 8)) int ima_policy_flag; static int temp_ima_appraise; diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 7a97c269a072..671fc50255f9 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -20,59 +20,6 @@ #include #include -/* iint action cache flags */ -#define IMA_MEASURE 0x00000001 -#define IMA_MEASURED 0x00000002 -#define IMA_APPRAISE 0x00000004 -#define IMA_APPRAISED 0x00000008 -/*#define IMA_COLLECT 0x00000010 do not use this flag */ -#define IMA_COLLECTED 0x00000020 -#define IMA_AUDIT 0x00000040 -#define IMA_AUDITED 0x00000080 -#define IMA_HASH 0x00000100 -#define IMA_HASHED 0x00000200 - -/* iint policy rule cache flags */ -#define IMA_NONACTION_FLAGS 0xff000000 -#define IMA_DIGSIG_REQUIRED 0x01000000 -#define IMA_PERMIT_DIRECTIO 0x02000000 -#define IMA_NEW_FILE 0x04000000 -#define IMA_FAIL_UNVERIFIABLE_SIGS 0x10000000 -#define IMA_MODSIG_ALLOWED 0x20000000 -#define IMA_CHECK_BLACKLIST 0x40000000 -#define IMA_VERITY_REQUIRED 0x80000000 - -#define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \ - IMA_HASH | IMA_APPRAISE_SUBMASK) -#define IMA_DONE_MASK (IMA_MEASURED | IMA_APPRAISED | IMA_AUDITED | \ - IMA_HASHED | IMA_COLLECTED | \ - IMA_APPRAISED_SUBMASK) - -/* iint subaction appraise cache flags */ -#define IMA_FILE_APPRAISE 0x00001000 -#define IMA_FILE_APPRAISED 0x00002000 -#define IMA_MMAP_APPRAISE 0x00004000 -#define IMA_MMAP_APPRAISED 0x00008000 -#define IMA_BPRM_APPRAISE 0x00010000 -#define IMA_BPRM_APPRAISED 0x00020000 -#define IMA_READ_APPRAISE 0x00040000 -#define IMA_READ_APPRAISED 0x00080000 -#define IMA_CREDS_APPRAISE 0x00100000 -#define IMA_CREDS_APPRAISED 0x00200000 -#define IMA_APPRAISE_SUBMASK (IMA_FILE_APPRAISE | IMA_MMAP_APPRAISE | \ - IMA_BPRM_APPRAISE | IMA_READ_APPRAISE | \ - IMA_CREDS_APPRAISE) -#define IMA_APPRAISED_SUBMASK (IMA_FILE_APPRAISED | IMA_MMAP_APPRAISED | \ - IMA_BPRM_APPRAISED | IMA_READ_APPRAISED | \ - IMA_CREDS_APPRAISED) - -/* iint cache atomic_flags */ -#define IMA_CHANGE_XATTR 0 -#define IMA_UPDATE_XATTR 1 -#define IMA_CHANGE_ATTR 2 -#define IMA_DIGSIG 3 -#define IMA_MUST_MEASURE 4 - enum evm_ima_xattr_type { IMA_XATTR_DIGEST = 0x01, EVM_XATTR_HMAC, -- cgit v1.2.3 From b6c0dec9f78bc691166d60347b52b3adf03d5875 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 15 Feb 2024 11:31:13 +0100 Subject: integrity: Remove LSM Since now IMA and EVM use their own integrity metadata, it is safe to remove the 'integrity' LSM, with its management of integrity metadata. Keep the iint.c file only for loading IMA and EVM keys at boot, and for creating the integrity directory in securityfs (we need to keep it for retrocompatibility reasons). Signed-off-by: Roberto Sassu Reviewed-by: Casey Schaufler Reviewed-by: Stefan Berger Reviewed-by: Mimi Zohar Acked-by: Mimi Zohar Signed-off-by: Paul Moore --- security/integrity/iint.c | 197 +---------------------------------------- security/integrity/integrity.h | 25 ------ security/security.c | 2 - 3 files changed, 2 insertions(+), 222 deletions(-) (limited to 'security') diff --git a/security/integrity/iint.c b/security/integrity/iint.c index d4419a2a1e24..068ac6c2ae1e 100644 --- a/security/integrity/iint.c +++ b/security/integrity/iint.c @@ -6,207 +6,14 @@ * Mimi Zohar * * File: integrity_iint.c - * - implements the integrity hooks: integrity_inode_alloc, - * integrity_inode_free - * - cache integrity information associated with an inode - * using a rbtree tree. + * - initialize the integrity directory in securityfs + * - load IMA and EVM keys */ -#include -#include -#include -#include -#include -#include #include -#include #include "integrity.h" -static struct rb_root integrity_iint_tree = RB_ROOT; -static DEFINE_RWLOCK(integrity_iint_lock); -static struct kmem_cache *iint_cache __ro_after_init; - struct dentry *integrity_dir; -/* - * __integrity_iint_find - return the iint associated with an inode - */ -static struct integrity_iint_cache *__integrity_iint_find(struct inode *inode) -{ - struct integrity_iint_cache *iint; - struct rb_node *n = integrity_iint_tree.rb_node; - - while (n) { - iint = rb_entry(n, struct integrity_iint_cache, rb_node); - - if (inode < iint->inode) - n = n->rb_left; - else if (inode > iint->inode) - n = n->rb_right; - else - return iint; - } - - return NULL; -} - -/* - * integrity_iint_find - return the iint associated with an inode - */ -struct integrity_iint_cache *integrity_iint_find(struct inode *inode) -{ - struct integrity_iint_cache *iint; - - if (!IS_IMA(inode)) - return NULL; - - read_lock(&integrity_iint_lock); - iint = __integrity_iint_find(inode); - read_unlock(&integrity_iint_lock); - - return iint; -} - -#define IMA_MAX_NESTING (FILESYSTEM_MAX_STACK_DEPTH+1) - -/* - * It is not clear that IMA should be nested at all, but as long is it measures - * files both on overlayfs and on underlying fs, we need to annotate the iint - * mutex to avoid lockdep false positives related to IMA + overlayfs. - * See ovl_lockdep_annotate_inode_mutex_key() for more details. - */ -static inline void iint_lockdep_annotate(struct integrity_iint_cache *iint, - struct inode *inode) -{ -#ifdef CONFIG_LOCKDEP - static struct lock_class_key iint_mutex_key[IMA_MAX_NESTING]; - - int depth = inode->i_sb->s_stack_depth; - - if (WARN_ON_ONCE(depth < 0 || depth >= IMA_MAX_NESTING)) - depth = 0; - - lockdep_set_class(&iint->mutex, &iint_mutex_key[depth]); -#endif -} - -static void iint_init_always(struct integrity_iint_cache *iint, - struct inode *inode) -{ - iint->ima_hash = NULL; - iint->version = 0; - iint->flags = 0UL; - iint->atomic_flags = 0UL; - iint->ima_file_status = INTEGRITY_UNKNOWN; - iint->ima_mmap_status = INTEGRITY_UNKNOWN; - iint->ima_bprm_status = INTEGRITY_UNKNOWN; - iint->ima_read_status = INTEGRITY_UNKNOWN; - iint->ima_creds_status = INTEGRITY_UNKNOWN; - iint->evm_status = INTEGRITY_UNKNOWN; - iint->measured_pcrs = 0; - mutex_init(&iint->mutex); - iint_lockdep_annotate(iint, inode); -} - -static void iint_free(struct integrity_iint_cache *iint) -{ - kfree(iint->ima_hash); - mutex_destroy(&iint->mutex); - kmem_cache_free(iint_cache, iint); -} - -/** - * integrity_inode_get - find or allocate an iint associated with an inode - * @inode: pointer to the inode - * @return: allocated iint - * - * Caller must lock i_mutex - */ -struct integrity_iint_cache *integrity_inode_get(struct inode *inode) -{ - struct rb_node **p; - struct rb_node *node, *parent = NULL; - struct integrity_iint_cache *iint, *test_iint; - - iint = integrity_iint_find(inode); - if (iint) - return iint; - - iint = kmem_cache_alloc(iint_cache, GFP_NOFS); - if (!iint) - return NULL; - - iint_init_always(iint, inode); - - write_lock(&integrity_iint_lock); - - p = &integrity_iint_tree.rb_node; - while (*p) { - parent = *p; - test_iint = rb_entry(parent, struct integrity_iint_cache, - rb_node); - if (inode < test_iint->inode) { - p = &(*p)->rb_left; - } else if (inode > test_iint->inode) { - p = &(*p)->rb_right; - } else { - write_unlock(&integrity_iint_lock); - kmem_cache_free(iint_cache, iint); - return test_iint; - } - } - - iint->inode = inode; - node = &iint->rb_node; - inode->i_flags |= S_IMA; - rb_link_node(node, parent, p); - rb_insert_color(node, &integrity_iint_tree); - - write_unlock(&integrity_iint_lock); - return iint; -} - -/** - * integrity_inode_free - called on security_inode_free - * @inode: pointer to the inode - * - * Free the integrity information(iint) associated with an inode. - */ -void integrity_inode_free(struct inode *inode) -{ - struct integrity_iint_cache *iint; - - if (!IS_IMA(inode)) - return; - - write_lock(&integrity_iint_lock); - iint = __integrity_iint_find(inode); - rb_erase(&iint->rb_node, &integrity_iint_tree); - write_unlock(&integrity_iint_lock); - - iint_free(iint); -} - -static void iint_init_once(void *foo) -{ - struct integrity_iint_cache *iint = (struct integrity_iint_cache *) foo; - - memset(iint, 0, sizeof(*iint)); -} - -static int __init integrity_iintcache_init(void) -{ - iint_cache = - kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache), - 0, SLAB_PANIC, iint_init_once); - return 0; -} -DEFINE_LSM(integrity) = { - .name = "integrity", - .init = integrity_iintcache_init, - .order = LSM_ORDER_LAST, -}; - - /* * integrity_kernel_read - read data from the file * diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 671fc50255f9..50d6f798e613 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -102,31 +102,6 @@ struct ima_file_id { __u8 hash[HASH_MAX_DIGESTSIZE]; } __packed; -/* integrity data associated with an inode */ -struct integrity_iint_cache { - struct rb_node rb_node; /* rooted in integrity_iint_tree */ - struct mutex mutex; /* protects: version, flags, digest */ - struct inode *inode; /* back pointer to inode in question */ - u64 version; /* track inode changes */ - unsigned long flags; - unsigned long measured_pcrs; - unsigned long atomic_flags; - unsigned long real_ino; - dev_t real_dev; - enum integrity_status ima_file_status:4; - enum integrity_status ima_mmap_status:4; - enum integrity_status ima_bprm_status:4; - enum integrity_status ima_read_status:4; - enum integrity_status ima_creds_status:4; - enum integrity_status evm_status:4; - struct ima_digest_data *ima_hash; -}; - -/* rbtree tree calls to lookup, insert, delete - * integrity data associated with an inode. - */ -struct integrity_iint_cache *integrity_iint_find(struct inode *inode); - int integrity_kernel_read(struct file *file, loff_t offset, void *addr, unsigned long count); diff --git a/security/security.c b/security/security.c index e08c1aa82edf..cbdc9bebe802 100644 --- a/security/security.c +++ b/security/security.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -1597,7 +1596,6 @@ static void inode_free_by_rcu(struct rcu_head *head) */ void security_inode_free(struct inode *inode) { - integrity_inode_free(inode); call_void_hook(inode_free_security, inode); /* * The inode may still be referenced in a path walk and -- cgit v1.2.3 From 85445b96429057d87446bcb24ec0cac9ea9c7fdf Mon Sep 17 00:00:00 2001 From: Coiby Xu Date: Tue, 9 Jan 2024 08:24:28 +0800 Subject: integrity: eliminate unnecessary "Problem loading X.509 certificate" msg Currently when the kernel fails to add a cert to the .machine keyring, it will throw an error immediately in the function integrity_add_key. Since the kernel will try adding to the .platform keyring next or throw an error (in the caller of integrity_add_key i.e. add_to_machine_keyring), so there is no need to throw an error immediately in integrity_add_key. Reported-by: itrymybest80@protonmail.com Closes: https://bugzilla.redhat.com/show_bug.cgi?id=2239331 Fixes: d19967764ba8 ("integrity: Introduce a Linux keyring called machine") Reviewed-by: Eric Snowberg Signed-off-by: Coiby Xu Signed-off-by: Mimi Zohar --- security/integrity/digsig.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'security') diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index df387de29bfa..45c3e5dda355 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c @@ -179,7 +179,8 @@ static int __init integrity_add_key(const unsigned int id, const void *data, KEY_ALLOC_NOT_IN_QUOTA); if (IS_ERR(key)) { rc = PTR_ERR(key); - pr_err("Problem loading X.509 certificate %d\n", rc); + if (id != INTEGRITY_KEYRING_MACHINE) + pr_err("Problem loading X.509 certificate %d\n", rc); } else { pr_notice("Loaded X.509 cert '%s'\n", key_ref_to_ptr(key)->description); -- cgit v1.2.3 From 936615f63768482be942644dd3b1b1dca862f25b Mon Sep 17 00:00:00 2001 From: Pairman Guo Date: Sat, 17 Feb 2024 21:35:04 +0800 Subject: lsm: fix typos in security/security.c comment headers This commit fixes several typos in comment headers in security/security.c where "Check is" should be "Check if". Signed-off-by: Pairman Guo [PM: subject line tweak] Signed-off-by: Paul Moore --- security/security.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'security') diff --git a/security/security.c b/security/security.c index cbdc9bebe802..c31e45da672b 100644 --- a/security/security.c +++ b/security/security.c @@ -2955,7 +2955,7 @@ int security_file_send_sigiotask(struct task_struct *tsk, } /** - * security_file_receive() - Check is receiving a file via IPC is allowed + * security_file_receive() - Check if receiving a file via IPC is allowed * @file: file being received * * This hook allows security modules to control the ability of a process to @@ -3182,7 +3182,7 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode) } /** - * security_kernel_module_request() - Check is loading a module is allowed + * security_kernel_module_request() - Check if loading a module is allowed * @kmod_name: module name * * Ability to trigger the kernel to automatically upcall to userspace for @@ -4155,7 +4155,7 @@ int security_netlink_send(struct sock *sk, struct sk_buff *skb) } /** - * security_ismaclabel() - Check is the named attribute is a MAC label + * security_ismaclabel() - Check if the named attribute is a MAC label * @name: full extended attribute name * * Check if the extended attribute specified by @name represents a MAC label. @@ -4528,7 +4528,7 @@ int security_socket_accept(struct socket *sock, struct socket *newsock) } /** - * security_socket_sendmsg() - Check is sending a message is allowed + * security_socket_sendmsg() - Check if sending a message is allowed * @sock: sending socket * @msg: message to send * @size: size of message -- cgit v1.2.3 From 260017f31a8c3879be5f9048a46f382b06c1923a Mon Sep 17 00:00:00 2001 From: Ondrej Mosnacek Date: Tue, 30 Jan 2024 13:56:59 +0100 Subject: lsm: use default hook return value in call_int_hook() Change the definition of call_int_hook() to treat LSM_RET_DEFAULT(...) as the "continue" value instead of 0. To further simplify this macro, also drop the IRC argument and replace it with LSM_RET_DEFAULT(...). After this the macro can be used in a couple more hooks, where similar logic is currently open-coded. At the same time, some other existing call_int_hook() users now need to be open-coded, but overall it's still a net simplification. There should be no functional change resulting from this patch. Signed-off-by: Ondrej Mosnacek Reviewed-by: Casey Schaufler [PM: merge fuzz due to other hook changes, tweaks from list discussion] Signed-off-by: Paul Moore --- security/security.c | 532 ++++++++++++++++++++++------------------------------ 1 file changed, 225 insertions(+), 307 deletions(-) (limited to 'security') diff --git a/security/security.c b/security/security.c index c31e45da672b..4cb832b00c40 100644 --- a/security/security.c +++ b/security/security.c @@ -855,14 +855,14 @@ out: P->hook.FUNC(__VA_ARGS__); \ } while (0) -#define call_int_hook(FUNC, IRC, ...) ({ \ - int RC = IRC; \ +#define call_int_hook(FUNC, ...) ({ \ + int RC = LSM_RET_DEFAULT(FUNC); \ do { \ struct security_hook_list *P; \ \ hlist_for_each_entry(P, &security_hook_heads.FUNC, list) { \ RC = P->hook.FUNC(__VA_ARGS__); \ - if (RC != 0) \ + if (RC != LSM_RET_DEFAULT(FUNC)) \ break; \ } \ } while (0); \ @@ -881,7 +881,7 @@ out: */ int security_binder_set_context_mgr(const struct cred *mgr) { - return call_int_hook(binder_set_context_mgr, 0, mgr); + return call_int_hook(binder_set_context_mgr, mgr); } /** @@ -896,7 +896,7 @@ int security_binder_set_context_mgr(const struct cred *mgr) int security_binder_transaction(const struct cred *from, const struct cred *to) { - return call_int_hook(binder_transaction, 0, from, to); + return call_int_hook(binder_transaction, from, to); } /** @@ -911,7 +911,7 @@ int security_binder_transaction(const struct cred *from, int security_binder_transfer_binder(const struct cred *from, const struct cred *to) { - return call_int_hook(binder_transfer_binder, 0, from, to); + return call_int_hook(binder_transfer_binder, from, to); } /** @@ -927,7 +927,7 @@ int security_binder_transfer_binder(const struct cred *from, int security_binder_transfer_file(const struct cred *from, const struct cred *to, const struct file *file) { - return call_int_hook(binder_transfer_file, 0, from, to, file); + return call_int_hook(binder_transfer_file, from, to, file); } /** @@ -946,7 +946,7 @@ int security_binder_transfer_file(const struct cred *from, */ int security_ptrace_access_check(struct task_struct *child, unsigned int mode) { - return call_int_hook(ptrace_access_check, 0, child, mode); + return call_int_hook(ptrace_access_check, child, mode); } /** @@ -961,7 +961,7 @@ int security_ptrace_access_check(struct task_struct *child, unsigned int mode) */ int security_ptrace_traceme(struct task_struct *parent) { - return call_int_hook(ptrace_traceme, 0, parent); + return call_int_hook(ptrace_traceme, parent); } /** @@ -983,8 +983,7 @@ int security_capget(const struct task_struct *target, kernel_cap_t *inheritable, kernel_cap_t *permitted) { - return call_int_hook(capget, 0, target, - effective, inheritable, permitted); + return call_int_hook(capget, target, effective, inheritable, permitted); } /** @@ -1005,8 +1004,8 @@ int security_capset(struct cred *new, const struct cred *old, const kernel_cap_t *inheritable, const kernel_cap_t *permitted) { - return call_int_hook(capset, 0, new, old, - effective, inheritable, permitted); + return call_int_hook(capset, new, old, effective, inheritable, + permitted); } /** @@ -1027,7 +1026,7 @@ int security_capable(const struct cred *cred, int cap, unsigned int opts) { - return call_int_hook(capable, 0, cred, ns, cap, opts); + return call_int_hook(capable, cred, ns, cap, opts); } /** @@ -1043,7 +1042,7 @@ int security_capable(const struct cred *cred, */ int security_quotactl(int cmds, int type, int id, const struct super_block *sb) { - return call_int_hook(quotactl, 0, cmds, type, id, sb); + return call_int_hook(quotactl, cmds, type, id, sb); } /** @@ -1056,7 +1055,7 @@ int security_quotactl(int cmds, int type, int id, const struct super_block *sb) */ int security_quota_on(struct dentry *dentry) { - return call_int_hook(quota_on, 0, dentry); + return call_int_hook(quota_on, dentry); } /** @@ -1071,7 +1070,7 @@ int security_quota_on(struct dentry *dentry) */ int security_syslog(int type) { - return call_int_hook(syslog, 0, type); + return call_int_hook(syslog, type); } /** @@ -1086,7 +1085,7 @@ int security_syslog(int type) */ int security_settime64(const struct timespec64 *ts, const struct timezone *tz) { - return call_int_hook(settime, 0, ts, tz); + return call_int_hook(settime, ts, tz); } /** @@ -1141,7 +1140,7 @@ int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) */ int security_bprm_creds_for_exec(struct linux_binprm *bprm) { - return call_int_hook(bprm_creds_for_exec, 0, bprm); + return call_int_hook(bprm_creds_for_exec, bprm); } /** @@ -1165,7 +1164,7 @@ int security_bprm_creds_for_exec(struct linux_binprm *bprm) */ int security_bprm_creds_from_file(struct linux_binprm *bprm, const struct file *file) { - return call_int_hook(bprm_creds_from_file, 0, bprm, file); + return call_int_hook(bprm_creds_from_file, bprm, file); } /** @@ -1182,7 +1181,7 @@ int security_bprm_creds_from_file(struct linux_binprm *bprm, const struct file * */ int security_bprm_check(struct linux_binprm *bprm) { - return call_int_hook(bprm_check_security, 0, bprm); + return call_int_hook(bprm_check_security, bprm); } /** @@ -1229,7 +1228,7 @@ void security_bprm_committed_creds(const struct linux_binprm *bprm) */ int security_fs_context_submount(struct fs_context *fc, struct super_block *reference) { - return call_int_hook(fs_context_submount, 0, fc, reference); + return call_int_hook(fs_context_submount, fc, reference); } /** @@ -1245,7 +1244,7 @@ int security_fs_context_submount(struct fs_context *fc, struct super_block *refe */ int security_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc) { - return call_int_hook(fs_context_dup, 0, fc, src_fc); + return call_int_hook(fs_context_dup, fc, src_fc); } /** @@ -1294,7 +1293,7 @@ int security_sb_alloc(struct super_block *sb) if (unlikely(rc)) return rc; - rc = call_int_hook(sb_alloc_security, 0, sb); + rc = call_int_hook(sb_alloc_security, sb); if (unlikely(rc)) security_sb_free(sb); return rc; @@ -1352,7 +1351,7 @@ EXPORT_SYMBOL(security_free_mnt_opts); */ int security_sb_eat_lsm_opts(char *options, void **mnt_opts) { - return call_int_hook(sb_eat_lsm_opts, 0, options, mnt_opts); + return call_int_hook(sb_eat_lsm_opts, options, mnt_opts); } EXPORT_SYMBOL(security_sb_eat_lsm_opts); @@ -1369,7 +1368,7 @@ EXPORT_SYMBOL(security_sb_eat_lsm_opts); int security_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts) { - return call_int_hook(sb_mnt_opts_compat, 0, sb, mnt_opts); + return call_int_hook(sb_mnt_opts_compat, sb, mnt_opts); } EXPORT_SYMBOL(security_sb_mnt_opts_compat); @@ -1386,7 +1385,7 @@ EXPORT_SYMBOL(security_sb_mnt_opts_compat); int security_sb_remount(struct super_block *sb, void *mnt_opts) { - return call_int_hook(sb_remount, 0, sb, mnt_opts); + return call_int_hook(sb_remount, sb, mnt_opts); } EXPORT_SYMBOL(security_sb_remount); @@ -1400,7 +1399,7 @@ EXPORT_SYMBOL(security_sb_remount); */ int security_sb_kern_mount(const struct super_block *sb) { - return call_int_hook(sb_kern_mount, 0, sb); + return call_int_hook(sb_kern_mount, sb); } /** @@ -1414,7 +1413,7 @@ int security_sb_kern_mount(const struct super_block *sb) */ int security_sb_show_options(struct seq_file *m, struct super_block *sb) { - return call_int_hook(sb_show_options, 0, m, sb); + return call_int_hook(sb_show_options, m, sb); } /** @@ -1428,7 +1427,7 @@ int security_sb_show_options(struct seq_file *m, struct super_block *sb) */ int security_sb_statfs(struct dentry *dentry) { - return call_int_hook(sb_statfs, 0, dentry); + return call_int_hook(sb_statfs, dentry); } /** @@ -1451,7 +1450,7 @@ int security_sb_statfs(struct dentry *dentry) int security_sb_mount(const char *dev_name, const struct path *path, const char *type, unsigned long flags, void *data) { - return call_int_hook(sb_mount, 0, dev_name, path, type, flags, data); + return call_int_hook(sb_mount, dev_name, path, type, flags, data); } /** @@ -1465,7 +1464,7 @@ int security_sb_mount(const char *dev_name, const struct path *path, */ int security_sb_umount(struct vfsmount *mnt, int flags) { - return call_int_hook(sb_umount, 0, mnt, flags); + return call_int_hook(sb_umount, mnt, flags); } /** @@ -1480,7 +1479,7 @@ int security_sb_umount(struct vfsmount *mnt, int flags) int security_sb_pivotroot(const struct path *old_path, const struct path *new_path) { - return call_int_hook(sb_pivotroot, 0, old_path, new_path); + return call_int_hook(sb_pivotroot, old_path, new_path); } /** @@ -1499,9 +1498,17 @@ int security_sb_set_mnt_opts(struct super_block *sb, unsigned long kern_flags, unsigned long *set_kern_flags) { - return call_int_hook(sb_set_mnt_opts, - mnt_opts ? -EOPNOTSUPP : 0, sb, - mnt_opts, kern_flags, set_kern_flags); + struct security_hook_list *hp; + int rc = mnt_opts ? -EOPNOTSUPP : LSM_RET_DEFAULT(sb_set_mnt_opts); + + hlist_for_each_entry(hp, &security_hook_heads.sb_set_mnt_opts, + list) { + rc = hp->hook.sb_set_mnt_opts(sb, mnt_opts, kern_flags, + set_kern_flags); + if (rc != LSM_RET_DEFAULT(sb_set_mnt_opts)) + break; + } + return rc; } EXPORT_SYMBOL(security_sb_set_mnt_opts); @@ -1521,7 +1528,7 @@ int security_sb_clone_mnt_opts(const struct super_block *oldsb, unsigned long kern_flags, unsigned long *set_kern_flags) { - return call_int_hook(sb_clone_mnt_opts, 0, oldsb, newsb, + return call_int_hook(sb_clone_mnt_opts, oldsb, newsb, kern_flags, set_kern_flags); } EXPORT_SYMBOL(security_sb_clone_mnt_opts); @@ -1538,7 +1545,7 @@ EXPORT_SYMBOL(security_sb_clone_mnt_opts); int security_move_mount(const struct path *from_path, const struct path *to_path) { - return call_int_hook(move_mount, 0, from_path, to_path); + return call_int_hook(move_mount, from_path, to_path); } /** @@ -1555,7 +1562,7 @@ int security_move_mount(const struct path *from_path, int security_path_notify(const struct path *path, u64 mask, unsigned int obj_type) { - return call_int_hook(path_notify, 0, path, mask, obj_type); + return call_int_hook(path_notify, path, mask, obj_type); } /** @@ -1574,7 +1581,7 @@ int security_inode_alloc(struct inode *inode) if (unlikely(rc)) return rc; - rc = call_int_hook(inode_alloc_security, 0, inode); + rc = call_int_hook(inode_alloc_security, inode); if (unlikely(rc)) security_inode_free(inode); return rc; @@ -1631,20 +1638,8 @@ int security_dentry_init_security(struct dentry *dentry, int mode, const char **xattr_name, void **ctx, u32 *ctxlen) { - struct security_hook_list *hp; - int rc; - - /* - * Only one module will provide a security context. - */ - hlist_for_each_entry(hp, &security_hook_heads.dentry_init_security, - list) { - rc = hp->hook.dentry_init_security(dentry, mode, name, - xattr_name, ctx, ctxlen); - if (rc != LSM_RET_DEFAULT(dentry_init_security)) - return rc; - } - return LSM_RET_DEFAULT(dentry_init_security); + return call_int_hook(dentry_init_security, dentry, mode, name, + xattr_name, ctx, ctxlen); } EXPORT_SYMBOL(security_dentry_init_security); @@ -1667,7 +1662,7 @@ int security_dentry_create_files_as(struct dentry *dentry, int mode, struct qstr *name, const struct cred *old, struct cred *new) { - return call_int_hook(dentry_create_files_as, 0, dentry, mode, + return call_int_hook(dentry_create_files_as, dentry, mode, name, old, new); } EXPORT_SYMBOL(security_dentry_create_files_as); @@ -1764,7 +1759,7 @@ int security_inode_init_security_anon(struct inode *inode, const struct qstr *name, const struct inode *context_inode) { - return call_int_hook(inode_init_security_anon, 0, inode, name, + return call_int_hook(inode_init_security_anon, inode, name, context_inode); } @@ -1786,7 +1781,7 @@ int security_path_mknod(const struct path *dir, struct dentry *dentry, { if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry)))) return 0; - return call_int_hook(path_mknod, 0, dir, dentry, mode, dev); + return call_int_hook(path_mknod, dir, dentry, mode, dev); } EXPORT_SYMBOL(security_path_mknod); @@ -1819,7 +1814,7 @@ int security_path_mkdir(const struct path *dir, struct dentry *dentry, { if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry)))) return 0; - return call_int_hook(path_mkdir, 0, dir, dentry, mode); + return call_int_hook(path_mkdir, dir, dentry, mode); } EXPORT_SYMBOL(security_path_mkdir); @@ -1836,7 +1831,7 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry)))) return 0; - return call_int_hook(path_rmdir, 0, dir, dentry); + return call_int_hook(path_rmdir, dir, dentry); } /** @@ -1852,7 +1847,7 @@ int security_path_unlink(const struct path *dir, struct dentry *dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry)))) return 0; - return call_int_hook(path_unlink, 0, dir, dentry); + return call_int_hook(path_unlink, dir, dentry); } EXPORT_SYMBOL(security_path_unlink); @@ -1871,7 +1866,7 @@ int security_path_symlink(const struct path *dir, struct dentry *dentry, { if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry)))) return 0; - return call_int_hook(path_symlink, 0, dir, dentry, old_name); + return call_int_hook(path_symlink, dir, dentry, old_name); } /** @@ -1889,7 +1884,7 @@ int security_path_link(struct dentry *old_dentry, const struct path *new_dir, { if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)))) return 0; - return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry); + return call_int_hook(path_link, old_dentry, new_dir, new_dentry); } /** @@ -1913,7 +1908,7 @@ int security_path_rename(const struct path *old_dir, struct dentry *old_dentry, IS_PRIVATE(d_backing_inode(new_dentry))))) return 0; - return call_int_hook(path_rename, 0, old_dir, old_dentry, new_dir, + return call_int_hook(path_rename, old_dir, old_dentry, new_dir, new_dentry, flags); } EXPORT_SYMBOL(security_path_rename); @@ -1932,7 +1927,7 @@ int security_path_truncate(const struct path *path) { if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) return 0; - return call_int_hook(path_truncate, 0, path); + return call_int_hook(path_truncate, path); } /** @@ -1950,7 +1945,7 @@ int security_path_chmod(const struct path *path, umode_t mode) { if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) return 0; - return call_int_hook(path_chmod, 0, path, mode); + return call_int_hook(path_chmod, path, mode); } /** @@ -1967,7 +1962,7 @@ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) { if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) return 0; - return call_int_hook(path_chown, 0, path, uid, gid); + return call_int_hook(path_chown, path, uid, gid); } /** @@ -1980,7 +1975,7 @@ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) */ int security_path_chroot(const struct path *path) { - return call_int_hook(path_chroot, 0, path); + return call_int_hook(path_chroot, path); } #endif /* CONFIG_SECURITY_PATH */ @@ -1999,7 +1994,7 @@ int security_inode_create(struct inode *dir, struct dentry *dentry, { if (unlikely(IS_PRIVATE(dir))) return 0; - return call_int_hook(inode_create, 0, dir, dentry, mode); + return call_int_hook(inode_create, dir, dentry, mode); } EXPORT_SYMBOL_GPL(security_inode_create); @@ -2033,7 +2028,7 @@ int security_inode_link(struct dentry *old_dentry, struct inode *dir, { if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)))) return 0; - return call_int_hook(inode_link, 0, old_dentry, dir, new_dentry); + return call_int_hook(inode_link, old_dentry, dir, new_dentry); } /** @@ -2049,7 +2044,7 @@ int security_inode_unlink(struct inode *dir, struct dentry *dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - return call_int_hook(inode_unlink, 0, dir, dentry); + return call_int_hook(inode_unlink, dir, dentry); } /** @@ -2067,7 +2062,7 @@ int security_inode_symlink(struct inode *dir, struct dentry *dentry, { if (unlikely(IS_PRIVATE(dir))) return 0; - return call_int_hook(inode_symlink, 0, dir, dentry, old_name); + return call_int_hook(inode_symlink, dir, dentry, old_name); } /** @@ -2085,7 +2080,7 @@ int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) { if (unlikely(IS_PRIVATE(dir))) return 0; - return call_int_hook(inode_mkdir, 0, dir, dentry, mode); + return call_int_hook(inode_mkdir, dir, dentry, mode); } EXPORT_SYMBOL_GPL(security_inode_mkdir); @@ -2102,7 +2097,7 @@ int security_inode_rmdir(struct inode *dir, struct dentry *dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - return call_int_hook(inode_rmdir, 0, dir, dentry); + return call_int_hook(inode_rmdir, dir, dentry); } /** @@ -2124,7 +2119,7 @@ int security_inode_mknod(struct inode *dir, struct dentry *dentry, { if (unlikely(IS_PRIVATE(dir))) return 0; - return call_int_hook(inode_mknod, 0, dir, dentry, mode, dev); + return call_int_hook(inode_mknod, dir, dentry, mode, dev); } /** @@ -2149,13 +2144,13 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry, return 0; if (flags & RENAME_EXCHANGE) { - int err = call_int_hook(inode_rename, 0, new_dir, new_dentry, + int err = call_int_hook(inode_rename, new_dir, new_dentry, old_dir, old_dentry); if (err) return err; } - return call_int_hook(inode_rename, 0, old_dir, old_dentry, + return call_int_hook(inode_rename, old_dir, old_dentry, new_dir, new_dentry); } @@ -2171,7 +2166,7 @@ int security_inode_readlink(struct dentry *dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - return call_int_hook(inode_readlink, 0, dentry); + return call_int_hook(inode_readlink, dentry); } /** @@ -2190,7 +2185,7 @@ int security_inode_follow_link(struct dentry *dentry, struct inode *inode, { if (unlikely(IS_PRIVATE(inode))) return 0; - return call_int_hook(inode_follow_link, 0, dentry, inode, rcu); + return call_int_hook(inode_follow_link, dentry, inode, rcu); } /** @@ -2211,7 +2206,7 @@ int security_inode_permission(struct inode *inode, int mask) { if (unlikely(IS_PRIVATE(inode))) return 0; - return call_int_hook(inode_permission, 0, inode, mask); + return call_int_hook(inode_permission, inode, mask); } /** @@ -2232,7 +2227,7 @@ int security_inode_setattr(struct mnt_idmap *idmap, { if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - return call_int_hook(inode_setattr, 0, idmap, dentry, attr); + return call_int_hook(inode_setattr, idmap, dentry, attr); } EXPORT_SYMBOL_GPL(security_inode_setattr); @@ -2264,7 +2259,7 @@ int security_inode_getattr(const struct path *path) { if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) return 0; - return call_int_hook(inode_getattr, 0, path); + return call_int_hook(inode_getattr, path); } /** @@ -2292,8 +2287,8 @@ int security_inode_setxattr(struct mnt_idmap *idmap, * SELinux and Smack integrate the cap call, * so assume that all LSMs supplying this call do so. */ - ret = call_int_hook(inode_setxattr, 1, idmap, dentry, name, value, - size, flags); + ret = call_int_hook(inode_setxattr, idmap, dentry, name, value, size, + flags); if (ret == 1) ret = cap_inode_setxattr(dentry, name, value, size, flags); @@ -2318,8 +2313,7 @@ int security_inode_set_acl(struct mnt_idmap *idmap, { if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - return call_int_hook(inode_set_acl, 0, idmap, dentry, acl_name, - kacl); + return call_int_hook(inode_set_acl, idmap, dentry, acl_name, kacl); } /** @@ -2355,7 +2349,7 @@ int security_inode_get_acl(struct mnt_idmap *idmap, { if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - return call_int_hook(inode_get_acl, 0, idmap, dentry, acl_name); + return call_int_hook(inode_get_acl, idmap, dentry, acl_name); } /** @@ -2374,7 +2368,7 @@ int security_inode_remove_acl(struct mnt_idmap *idmap, { if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - return call_int_hook(inode_remove_acl, 0, idmap, dentry, acl_name); + return call_int_hook(inode_remove_acl, idmap, dentry, acl_name); } /** @@ -2426,7 +2420,7 @@ int security_inode_getxattr(struct dentry *dentry, const char *name) { if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - return call_int_hook(inode_getxattr, 0, dentry, name); + return call_int_hook(inode_getxattr, dentry, name); } /** @@ -2442,7 +2436,7 @@ int security_inode_listxattr(struct dentry *dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - return call_int_hook(inode_listxattr, 0, dentry); + return call_int_hook(inode_listxattr, dentry); } /** @@ -2467,7 +2461,7 @@ int security_inode_removexattr(struct mnt_idmap *idmap, * SELinux and Smack integrate the cap call, * so assume that all LSMs supplying this call do so. */ - ret = call_int_hook(inode_removexattr, 1, idmap, dentry, name); + ret = call_int_hook(inode_removexattr, idmap, dentry, name); if (ret == 1) ret = cap_inode_removexattr(idmap, dentry, name); return ret; @@ -2500,7 +2494,7 @@ void security_inode_post_removexattr(struct dentry *dentry, const char *name) */ int security_inode_need_killpriv(struct dentry *dentry) { - return call_int_hook(inode_need_killpriv, 0, dentry); + return call_int_hook(inode_need_killpriv, dentry); } /** @@ -2517,7 +2511,7 @@ int security_inode_need_killpriv(struct dentry *dentry) int security_inode_killpriv(struct mnt_idmap *idmap, struct dentry *dentry) { - return call_int_hook(inode_killpriv, 0, idmap, dentry); + return call_int_hook(inode_killpriv, idmap, dentry); } /** @@ -2540,21 +2534,11 @@ int security_inode_getsecurity(struct mnt_idmap *idmap, struct inode *inode, const char *name, void **buffer, bool alloc) { - struct security_hook_list *hp; - int rc; - if (unlikely(IS_PRIVATE(inode))) return LSM_RET_DEFAULT(inode_getsecurity); - /* - * Only one module will provide an attribute with a given name. - */ - hlist_for_each_entry(hp, &security_hook_heads.inode_getsecurity, list) { - rc = hp->hook.inode_getsecurity(idmap, inode, name, buffer, - alloc); - if (rc != LSM_RET_DEFAULT(inode_getsecurity)) - return rc; - } - return LSM_RET_DEFAULT(inode_getsecurity); + + return call_int_hook(inode_getsecurity, idmap, inode, name, buffer, + alloc); } /** @@ -2575,21 +2559,11 @@ int security_inode_getsecurity(struct mnt_idmap *idmap, int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) { - struct security_hook_list *hp; - int rc; - if (unlikely(IS_PRIVATE(inode))) return LSM_RET_DEFAULT(inode_setsecurity); - /* - * Only one module will provide an attribute with a given name. - */ - hlist_for_each_entry(hp, &security_hook_heads.inode_setsecurity, list) { - rc = hp->hook.inode_setsecurity(inode, name, value, size, - flags); - if (rc != LSM_RET_DEFAULT(inode_setsecurity)) - return rc; - } - return LSM_RET_DEFAULT(inode_setsecurity); + + return call_int_hook(inode_setsecurity, inode, name, value, size, + flags); } /** @@ -2610,7 +2584,7 @@ int security_inode_listsecurity(struct inode *inode, { if (unlikely(IS_PRIVATE(inode))) return 0; - return call_int_hook(inode_listsecurity, 0, inode, buffer, buffer_size); + return call_int_hook(inode_listsecurity, inode, buffer, buffer_size); } EXPORT_SYMBOL(security_inode_listsecurity); @@ -2641,7 +2615,7 @@ void security_inode_getsecid(struct inode *inode, u32 *secid) */ int security_inode_copy_up(struct dentry *src, struct cred **new) { - return call_int_hook(inode_copy_up, 0, src, new); + return call_int_hook(inode_copy_up, src, new); } EXPORT_SYMBOL(security_inode_copy_up); @@ -2659,7 +2633,6 @@ EXPORT_SYMBOL(security_inode_copy_up); */ int security_inode_copy_up_xattr(const char *name) { - struct security_hook_list *hp; int rc; /* @@ -2667,12 +2640,9 @@ int security_inode_copy_up_xattr(const char *name) * xattr), -EOPNOTSUPP if it does not know anything about the xattr or * any other error code in case of an error. */ - hlist_for_each_entry(hp, - &security_hook_heads.inode_copy_up_xattr, list) { - rc = hp->hook.inode_copy_up_xattr(name); - if (rc != LSM_RET_DEFAULT(inode_copy_up_xattr)) - return rc; - } + rc = call_int_hook(inode_copy_up_xattr, name); + if (rc != LSM_RET_DEFAULT(inode_copy_up_xattr)) + return rc; return LSM_RET_DEFAULT(inode_copy_up_xattr); } @@ -2691,7 +2661,7 @@ EXPORT_SYMBOL(security_inode_copy_up_xattr); int security_kernfs_init_security(struct kernfs_node *kn_dir, struct kernfs_node *kn) { - return call_int_hook(kernfs_init_security, 0, kn_dir, kn); + return call_int_hook(kernfs_init_security, kn_dir, kn); } /** @@ -2715,7 +2685,7 @@ int security_kernfs_init_security(struct kernfs_node *kn_dir, */ int security_file_permission(struct file *file, int mask) { - return call_int_hook(file_permission, 0, file, mask); + return call_int_hook(file_permission, file, mask); } /** @@ -2733,7 +2703,7 @@ int security_file_alloc(struct file *file) if (rc) return rc; - rc = call_int_hook(file_alloc_security, 0, file); + rc = call_int_hook(file_alloc_security, file); if (unlikely(rc)) security_file_free(file); return rc; @@ -2784,7 +2754,7 @@ void security_file_free(struct file *file) */ int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - return call_int_hook(file_ioctl, 0, file, cmd, arg); + return call_int_hook(file_ioctl, file, cmd, arg); } EXPORT_SYMBOL_GPL(security_file_ioctl); @@ -2802,7 +2772,7 @@ EXPORT_SYMBOL_GPL(security_file_ioctl); int security_file_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) { - return call_int_hook(file_ioctl_compat, 0, file, cmd, arg); + return call_int_hook(file_ioctl_compat, file, cmd, arg); } EXPORT_SYMBOL_GPL(security_file_ioctl_compat); @@ -2853,7 +2823,7 @@ static inline unsigned long mmap_prot(struct file *file, unsigned long prot) int security_mmap_file(struct file *file, unsigned long prot, unsigned long flags) { - return call_int_hook(mmap_file, 0, file, prot, mmap_prot(file, prot), + return call_int_hook(mmap_file, file, prot, mmap_prot(file, prot), flags); } @@ -2867,7 +2837,7 @@ int security_mmap_file(struct file *file, unsigned long prot, */ int security_mmap_addr(unsigned long addr) { - return call_int_hook(mmap_addr, 0, addr); + return call_int_hook(mmap_addr, addr); } /** @@ -2883,7 +2853,7 @@ int security_mmap_addr(unsigned long addr) int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, unsigned long prot) { - return call_int_hook(file_mprotect, 0, vma, reqprot, prot); + return call_int_hook(file_mprotect, vma, reqprot, prot); } /** @@ -2898,7 +2868,7 @@ int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, */ int security_file_lock(struct file *file, unsigned int cmd) { - return call_int_hook(file_lock, 0, file, cmd); + return call_int_hook(file_lock, file, cmd); } /** @@ -2917,7 +2887,7 @@ int security_file_lock(struct file *file, unsigned int cmd) */ int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg) { - return call_int_hook(file_fcntl, 0, file, cmd, arg); + return call_int_hook(file_fcntl, file, cmd, arg); } /** @@ -2951,7 +2921,7 @@ void security_file_set_fowner(struct file *file) int security_file_send_sigiotask(struct task_struct *tsk, struct fown_struct *fown, int sig) { - return call_int_hook(file_send_sigiotask, 0, tsk, fown, sig); + return call_int_hook(file_send_sigiotask, tsk, fown, sig); } /** @@ -2965,7 +2935,7 @@ int security_file_send_sigiotask(struct task_struct *tsk, */ int security_file_receive(struct file *file) { - return call_int_hook(file_receive, 0, file); + return call_int_hook(file_receive, file); } /** @@ -2981,7 +2951,7 @@ int security_file_open(struct file *file) { int ret; - ret = call_int_hook(file_open, 0, file); + ret = call_int_hook(file_open, file); if (ret) return ret; @@ -3001,7 +2971,7 @@ int security_file_open(struct file *file) */ int security_file_post_open(struct file *file, int mask) { - return call_int_hook(file_post_open, 0, file, mask); + return call_int_hook(file_post_open, file, mask); } EXPORT_SYMBOL_GPL(security_file_post_open); @@ -3017,7 +2987,7 @@ EXPORT_SYMBOL_GPL(security_file_post_open); */ int security_file_truncate(struct file *file) { - return call_int_hook(file_truncate, 0, file); + return call_int_hook(file_truncate, file); } /** @@ -3035,7 +3005,7 @@ int security_task_alloc(struct task_struct *task, unsigned long clone_flags) if (rc) return rc; - rc = call_int_hook(task_alloc, 0, task, clone_flags); + rc = call_int_hook(task_alloc, task, clone_flags); if (unlikely(rc)) security_task_free(task); return rc; @@ -3073,7 +3043,7 @@ int security_cred_alloc_blank(struct cred *cred, gfp_t gfp) if (rc) return rc; - rc = call_int_hook(cred_alloc_blank, 0, cred, gfp); + rc = call_int_hook(cred_alloc_blank, cred, gfp); if (unlikely(rc)) security_cred_free(cred); return rc; @@ -3117,7 +3087,7 @@ int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp) if (rc) return rc; - rc = call_int_hook(cred_prepare, 0, new, old, gfp); + rc = call_int_hook(cred_prepare, new, old, gfp); if (unlikely(rc)) security_cred_free(new); return rc; @@ -3162,7 +3132,7 @@ EXPORT_SYMBOL(security_cred_getsecid); */ int security_kernel_act_as(struct cred *new, u32 secid) { - return call_int_hook(kernel_act_as, 0, new, secid); + return call_int_hook(kernel_act_as, new, secid); } /** @@ -3178,7 +3148,7 @@ int security_kernel_act_as(struct cred *new, u32 secid) */ int security_kernel_create_files_as(struct cred *new, struct inode *inode) { - return call_int_hook(kernel_create_files_as, 0, new, inode); + return call_int_hook(kernel_create_files_as, new, inode); } /** @@ -3192,7 +3162,7 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode) */ int security_kernel_module_request(char *kmod_name) { - return call_int_hook(kernel_module_request, 0, kmod_name); + return call_int_hook(kernel_module_request, kmod_name); } /** @@ -3208,7 +3178,7 @@ int security_kernel_module_request(char *kmod_name) int security_kernel_read_file(struct file *file, enum kernel_read_file_id id, bool contents) { - return call_int_hook(kernel_read_file, 0, file, id, contents); + return call_int_hook(kernel_read_file, file, id, contents); } EXPORT_SYMBOL_GPL(security_kernel_read_file); @@ -3228,7 +3198,7 @@ EXPORT_SYMBOL_GPL(security_kernel_read_file); int security_kernel_post_read_file(struct file *file, char *buf, loff_t size, enum kernel_read_file_id id) { - return call_int_hook(kernel_post_read_file, 0, file, buf, size, id); + return call_int_hook(kernel_post_read_file, file, buf, size, id); } EXPORT_SYMBOL_GPL(security_kernel_post_read_file); @@ -3243,7 +3213,7 @@ EXPORT_SYMBOL_GPL(security_kernel_post_read_file); */ int security_kernel_load_data(enum kernel_load_data_id id, bool contents) { - return call_int_hook(kernel_load_data, 0, id, contents); + return call_int_hook(kernel_load_data, id, contents); } EXPORT_SYMBOL_GPL(security_kernel_load_data); @@ -3265,8 +3235,7 @@ int security_kernel_post_load_data(char *buf, loff_t size, enum kernel_load_data_id id, char *description) { - return call_int_hook(kernel_post_load_data, 0, buf, size, id, - description); + return call_int_hook(kernel_post_load_data, buf, size, id, description); } EXPORT_SYMBOL_GPL(security_kernel_post_load_data); @@ -3287,7 +3256,7 @@ EXPORT_SYMBOL_GPL(security_kernel_post_load_data); int security_task_fix_setuid(struct cred *new, const struct cred *old, int flags) { - return call_int_hook(task_fix_setuid, 0, new, old, flags); + return call_int_hook(task_fix_setuid, new, old, flags); } /** @@ -3307,7 +3276,7 @@ int security_task_fix_setuid(struct cred *new, const struct cred *old, int security_task_fix_setgid(struct cred *new, const struct cred *old, int flags) { - return call_int_hook(task_fix_setgid, 0, new, old, flags); + return call_int_hook(task_fix_setgid, new, old, flags); } /** @@ -3324,7 +3293,7 @@ int security_task_fix_setgid(struct cred *new, const struct cred *old, */ int security_task_fix_setgroups(struct cred *new, const struct cred *old) { - return call_int_hook(task_fix_setgroups, 0, new, old); + return call_int_hook(task_fix_setgroups, new, old); } /** @@ -3339,7 +3308,7 @@ int security_task_fix_setgroups(struct cred *new, const struct cred *old) */ int security_task_setpgid(struct task_struct *p, pid_t pgid) { - return call_int_hook(task_setpgid, 0, p, pgid); + return call_int_hook(task_setpgid, p, pgid); } /** @@ -3353,7 +3322,7 @@ int security_task_setpgid(struct task_struct *p, pid_t pgid) */ int security_task_getpgid(struct task_struct *p) { - return call_int_hook(task_getpgid, 0, p); + return call_int_hook(task_getpgid, p); } /** @@ -3366,7 +3335,7 @@ int security_task_getpgid(struct task_struct *p) */ int security_task_getsid(struct task_struct *p) { - return call_int_hook(task_getsid, 0, p); + return call_int_hook(task_getsid, p); } /** @@ -3409,7 +3378,7 @@ EXPORT_SYMBOL(security_task_getsecid_obj); */ int security_task_setnice(struct task_struct *p, int nice) { - return call_int_hook(task_setnice, 0, p, nice); + return call_int_hook(task_setnice, p, nice); } /** @@ -3423,7 +3392,7 @@ int security_task_setnice(struct task_struct *p, int nice) */ int security_task_setioprio(struct task_struct *p, int ioprio) { - return call_int_hook(task_setioprio, 0, p, ioprio); + return call_int_hook(task_setioprio, p, ioprio); } /** @@ -3436,7 +3405,7 @@ int security_task_setioprio(struct task_struct *p, int ioprio) */ int security_task_getioprio(struct task_struct *p) { - return call_int_hook(task_getioprio, 0, p); + return call_int_hook(task_getioprio, p); } /** @@ -3453,7 +3422,7 @@ int security_task_getioprio(struct task_struct *p) int security_task_prlimit(const struct cred *cred, const struct cred *tcred, unsigned int flags) { - return call_int_hook(task_prlimit, 0, cred, tcred, flags); + return call_int_hook(task_prlimit, cred, tcred, flags); } /** @@ -3471,7 +3440,7 @@ int security_task_prlimit(const struct cred *cred, const struct cred *tcred, int security_task_setrlimit(struct task_struct *p, unsigned int resource, struct rlimit *new_rlim) { - return call_int_hook(task_setrlimit, 0, p, resource, new_rlim); + return call_int_hook(task_setrlimit, p, resource, new_rlim); } /** @@ -3485,7 +3454,7 @@ int security_task_setrlimit(struct task_struct *p, unsigned int resource, */ int security_task_setscheduler(struct task_struct *p) { - return call_int_hook(task_setscheduler, 0, p); + return call_int_hook(task_setscheduler, p); } /** @@ -3498,7 +3467,7 @@ int security_task_setscheduler(struct task_struct *p) */ int security_task_getscheduler(struct task_struct *p) { - return call_int_hook(task_getscheduler, 0, p); + return call_int_hook(task_getscheduler, p); } /** @@ -3511,7 +3480,7 @@ int security_task_getscheduler(struct task_struct *p) */ int security_task_movememory(struct task_struct *p) { - return call_int_hook(task_movememory, 0, p); + return call_int_hook(task_movememory, p); } /** @@ -3532,7 +3501,7 @@ int security_task_movememory(struct task_struct *p) int security_task_kill(struct task_struct *p, struct kernel_siginfo *info, int sig, const struct cred *cred) { - return call_int_hook(task_kill, 0, p, info, sig, cred); + return call_int_hook(task_kill, p, info, sig, cred); } /** @@ -3590,7 +3559,7 @@ void security_task_to_inode(struct task_struct *p, struct inode *inode) */ int security_create_user_ns(const struct cred *cred) { - return call_int_hook(userns_create, 0, cred); + return call_int_hook(userns_create, cred); } /** @@ -3604,7 +3573,7 @@ int security_create_user_ns(const struct cred *cred) */ int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag) { - return call_int_hook(ipc_permission, 0, ipcp, flag); + return call_int_hook(ipc_permission, ipcp, flag); } /** @@ -3636,7 +3605,7 @@ int security_msg_msg_alloc(struct msg_msg *msg) if (unlikely(rc)) return rc; - rc = call_int_hook(msg_msg_alloc_security, 0, msg); + rc = call_int_hook(msg_msg_alloc_security, msg); if (unlikely(rc)) security_msg_msg_free(msg); return rc; @@ -3670,7 +3639,7 @@ int security_msg_queue_alloc(struct kern_ipc_perm *msq) if (unlikely(rc)) return rc; - rc = call_int_hook(msg_queue_alloc_security, 0, msq); + rc = call_int_hook(msg_queue_alloc_security, msq); if (unlikely(rc)) security_msg_queue_free(msq); return rc; @@ -3702,7 +3671,7 @@ void security_msg_queue_free(struct kern_ipc_perm *msq) */ int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) { - return call_int_hook(msg_queue_associate, 0, msq, msqflg); + return call_int_hook(msg_queue_associate, msq, msqflg); } /** @@ -3717,7 +3686,7 @@ int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) */ int security_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd) { - return call_int_hook(msg_queue_msgctl, 0, msq, cmd); + return call_int_hook(msg_queue_msgctl, msq, cmd); } /** @@ -3734,7 +3703,7 @@ int security_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd) int security_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *msg, int msqflg) { - return call_int_hook(msg_queue_msgsnd, 0, msq, msg, msqflg); + return call_int_hook(msg_queue_msgsnd, msq, msg, msqflg); } /** @@ -3755,7 +3724,7 @@ int security_msg_queue_msgsnd(struct kern_ipc_perm *msq, int security_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg, struct task_struct *target, long type, int mode) { - return call_int_hook(msg_queue_msgrcv, 0, msq, msg, target, type, mode); + return call_int_hook(msg_queue_msgrcv, msq, msg, target, type, mode); } /** @@ -3773,7 +3742,7 @@ int security_shm_alloc(struct kern_ipc_perm *shp) if (unlikely(rc)) return rc; - rc = call_int_hook(shm_alloc_security, 0, shp); + rc = call_int_hook(shm_alloc_security, shp); if (unlikely(rc)) security_shm_free(shp); return rc; @@ -3806,7 +3775,7 @@ void security_shm_free(struct kern_ipc_perm *shp) */ int security_shm_associate(struct kern_ipc_perm *shp, int shmflg) { - return call_int_hook(shm_associate, 0, shp, shmflg); + return call_int_hook(shm_associate, shp, shmflg); } /** @@ -3821,7 +3790,7 @@ int security_shm_associate(struct kern_ipc_perm *shp, int shmflg) */ int security_shm_shmctl(struct kern_ipc_perm *shp, int cmd) { - return call_int_hook(shm_shmctl, 0, shp, cmd); + return call_int_hook(shm_shmctl, shp, cmd); } /** @@ -3839,7 +3808,7 @@ int security_shm_shmctl(struct kern_ipc_perm *shp, int cmd) int security_shm_shmat(struct kern_ipc_perm *shp, char __user *shmaddr, int shmflg) { - return call_int_hook(shm_shmat, 0, shp, shmaddr, shmflg); + return call_int_hook(shm_shmat, shp, shmaddr, shmflg); } /** @@ -3857,7 +3826,7 @@ int security_sem_alloc(struct kern_ipc_perm *sma) if (unlikely(rc)) return rc; - rc = call_int_hook(sem_alloc_security, 0, sma); + rc = call_int_hook(sem_alloc_security, sma); if (unlikely(rc)) security_sem_free(sma); return rc; @@ -3889,7 +3858,7 @@ void security_sem_free(struct kern_ipc_perm *sma) */ int security_sem_associate(struct kern_ipc_perm *sma, int semflg) { - return call_int_hook(sem_associate, 0, sma, semflg); + return call_int_hook(sem_associate, sma, semflg); } /** @@ -3904,7 +3873,7 @@ int security_sem_associate(struct kern_ipc_perm *sma, int semflg) */ int security_sem_semctl(struct kern_ipc_perm *sma, int cmd) { - return call_int_hook(sem_semctl, 0, sma, cmd); + return call_int_hook(sem_semctl, sma, cmd); } /** @@ -3922,7 +3891,7 @@ int security_sem_semctl(struct kern_ipc_perm *sma, int cmd) int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops, unsigned nsops, int alter) { - return call_int_hook(sem_semop, 0, sma, sops, nsops, alter); + return call_int_hook(sem_semop, sma, sops, nsops, alter); } /** @@ -4151,7 +4120,7 @@ int security_setprocattr(int lsmid, const char *name, void *value, size_t size) */ int security_netlink_send(struct sock *sk, struct sk_buff *skb) { - return call_int_hook(netlink_send, 0, sk, skb); + return call_int_hook(netlink_send, sk, skb); } /** @@ -4164,7 +4133,7 @@ int security_netlink_send(struct sock *sk, struct sk_buff *skb) */ int security_ismaclabel(const char *name) { - return call_int_hook(ismaclabel, 0, name); + return call_int_hook(ismaclabel, name); } EXPORT_SYMBOL(security_ismaclabel); @@ -4183,20 +4152,7 @@ EXPORT_SYMBOL(security_ismaclabel); */ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) { - struct security_hook_list *hp; - int rc; - - /* - * Currently, only one LSM can implement secid_to_secctx (i.e this - * LSM hook is not "stackable"). - */ - hlist_for_each_entry(hp, &security_hook_heads.secid_to_secctx, list) { - rc = hp->hook.secid_to_secctx(secid, secdata, seclen); - if (rc != LSM_RET_DEFAULT(secid_to_secctx)) - return rc; - } - - return LSM_RET_DEFAULT(secid_to_secctx); + return call_int_hook(secid_to_secctx, secid, secdata, seclen); } EXPORT_SYMBOL(security_secid_to_secctx); @@ -4213,7 +4169,7 @@ EXPORT_SYMBOL(security_secid_to_secctx); int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) { *secid = 0; - return call_int_hook(secctx_to_secid, 0, secdata, seclen, secid); + return call_int_hook(secctx_to_secid, secdata, seclen, secid); } EXPORT_SYMBOL(security_secctx_to_secid); @@ -4260,7 +4216,7 @@ EXPORT_SYMBOL(security_inode_invalidate_secctx); */ int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) { - return call_int_hook(inode_notifysecctx, 0, inode, ctx, ctxlen); + return call_int_hook(inode_notifysecctx, inode, ctx, ctxlen); } EXPORT_SYMBOL(security_inode_notifysecctx); @@ -4282,7 +4238,7 @@ EXPORT_SYMBOL(security_inode_notifysecctx); */ int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) { - return call_int_hook(inode_setsecctx, 0, dentry, ctx, ctxlen); + return call_int_hook(inode_setsecctx, dentry, ctx, ctxlen); } EXPORT_SYMBOL(security_inode_setsecctx); @@ -4299,19 +4255,7 @@ EXPORT_SYMBOL(security_inode_setsecctx); */ int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) { - struct security_hook_list *hp; - int rc; - - /* - * Only one module will provide a security context. - */ - hlist_for_each_entry(hp, &security_hook_heads.inode_getsecctx, list) { - rc = hp->hook.inode_getsecctx(inode, ctx, ctxlen); - if (rc != LSM_RET_DEFAULT(inode_getsecctx)) - return rc; - } - - return LSM_RET_DEFAULT(inode_getsecctx); + return call_int_hook(inode_getsecctx, inode, ctx, ctxlen); } EXPORT_SYMBOL(security_inode_getsecctx); @@ -4330,7 +4274,7 @@ int security_post_notification(const struct cred *w_cred, const struct cred *cred, struct watch_notification *n) { - return call_int_hook(post_notification, 0, w_cred, cred, n); + return call_int_hook(post_notification, w_cred, cred, n); } #endif /* CONFIG_WATCH_QUEUE */ @@ -4346,7 +4290,7 @@ int security_post_notification(const struct cred *w_cred, */ int security_watch_key(struct key *key) { - return call_int_hook(watch_key, 0, key); + return call_int_hook(watch_key, key); } #endif /* CONFIG_KEY_NOTIFICATIONS */ @@ -4375,7 +4319,7 @@ int security_watch_key(struct key *key) int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk) { - return call_int_hook(unix_stream_connect, 0, sock, other, newsk); + return call_int_hook(unix_stream_connect, sock, other, newsk); } EXPORT_SYMBOL(security_unix_stream_connect); @@ -4401,7 +4345,7 @@ EXPORT_SYMBOL(security_unix_stream_connect); */ int security_unix_may_send(struct socket *sock, struct socket *other) { - return call_int_hook(unix_may_send, 0, sock, other); + return call_int_hook(unix_may_send, sock, other); } EXPORT_SYMBOL(security_unix_may_send); @@ -4418,7 +4362,7 @@ EXPORT_SYMBOL(security_unix_may_send); */ int security_socket_create(int family, int type, int protocol, int kern) { - return call_int_hook(socket_create, 0, family, type, protocol, kern); + return call_int_hook(socket_create, family, type, protocol, kern); } /** @@ -4442,7 +4386,7 @@ int security_socket_create(int family, int type, int protocol, int kern) int security_socket_post_create(struct socket *sock, int family, int type, int protocol, int kern) { - return call_int_hook(socket_post_create, 0, sock, family, type, + return call_int_hook(socket_post_create, sock, family, type, protocol, kern); } @@ -4458,7 +4402,7 @@ int security_socket_post_create(struct socket *sock, int family, */ int security_socket_socketpair(struct socket *socka, struct socket *sockb) { - return call_int_hook(socket_socketpair, 0, socka, sockb); + return call_int_hook(socket_socketpair, socka, sockb); } EXPORT_SYMBOL(security_socket_socketpair); @@ -4477,7 +4421,7 @@ EXPORT_SYMBOL(security_socket_socketpair); int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) { - return call_int_hook(socket_bind, 0, sock, address, addrlen); + return call_int_hook(socket_bind, sock, address, addrlen); } /** @@ -4494,7 +4438,7 @@ int security_socket_bind(struct socket *sock, int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) { - return call_int_hook(socket_connect, 0, sock, address, addrlen); + return call_int_hook(socket_connect, sock, address, addrlen); } /** @@ -4508,7 +4452,7 @@ int security_socket_connect(struct socket *sock, */ int security_socket_listen(struct socket *sock, int backlog) { - return call_int_hook(socket_listen, 0, sock, backlog); + return call_int_hook(socket_listen, sock, backlog); } /** @@ -4524,7 +4468,7 @@ int security_socket_listen(struct socket *sock, int backlog) */ int security_socket_accept(struct socket *sock, struct socket *newsock) { - return call_int_hook(socket_accept, 0, sock, newsock); + return call_int_hook(socket_accept, sock, newsock); } /** @@ -4539,7 +4483,7 @@ int security_socket_accept(struct socket *sock, struct socket *newsock) */ int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) { - return call_int_hook(socket_sendmsg, 0, sock, msg, size); + return call_int_hook(socket_sendmsg, sock, msg, size); } /** @@ -4556,7 +4500,7 @@ int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) int security_socket_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags) { - return call_int_hook(socket_recvmsg, 0, sock, msg, size, flags); + return call_int_hook(socket_recvmsg, sock, msg, size, flags); } /** @@ -4570,7 +4514,7 @@ int security_socket_recvmsg(struct socket *sock, struct msghdr *msg, */ int security_socket_getsockname(struct socket *sock) { - return call_int_hook(socket_getsockname, 0, sock); + return call_int_hook(socket_getsockname, sock); } /** @@ -4583,7 +4527,7 @@ int security_socket_getsockname(struct socket *sock) */ int security_socket_getpeername(struct socket *sock) { - return call_int_hook(socket_getpeername, 0, sock); + return call_int_hook(socket_getpeername, sock); } /** @@ -4599,7 +4543,7 @@ int security_socket_getpeername(struct socket *sock) */ int security_socket_getsockopt(struct socket *sock, int level, int optname) { - return call_int_hook(socket_getsockopt, 0, sock, level, optname); + return call_int_hook(socket_getsockopt, sock, level, optname); } /** @@ -4614,7 +4558,7 @@ int security_socket_getsockopt(struct socket *sock, int level, int optname) */ int security_socket_setsockopt(struct socket *sock, int level, int optname) { - return call_int_hook(socket_setsockopt, 0, sock, level, optname); + return call_int_hook(socket_setsockopt, sock, level, optname); } /** @@ -4629,7 +4573,7 @@ int security_socket_setsockopt(struct socket *sock, int level, int optname) */ int security_socket_shutdown(struct socket *sock, int how) { - return call_int_hook(socket_shutdown, 0, sock, how); + return call_int_hook(socket_shutdown, sock, how); } /** @@ -4646,7 +4590,7 @@ int security_socket_shutdown(struct socket *sock, int how) */ int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) { - return call_int_hook(socket_sock_rcv_skb, 0, sk, skb); + return call_int_hook(socket_sock_rcv_skb, sk, skb); } EXPORT_SYMBOL(security_sock_rcv_skb); @@ -4668,20 +4612,8 @@ EXPORT_SYMBOL(security_sock_rcv_skb); int security_socket_getpeersec_stream(struct socket *sock, sockptr_t optval, sockptr_t optlen, unsigned int len) { - struct security_hook_list *hp; - int rc; - - /* - * Only one module will provide a security context. - */ - hlist_for_each_entry(hp, &security_hook_heads.socket_getpeersec_stream, - list) { - rc = hp->hook.socket_getpeersec_stream(sock, optval, optlen, - len); - if (rc != LSM_RET_DEFAULT(socket_getpeersec_stream)) - return rc; - } - return LSM_RET_DEFAULT(socket_getpeersec_stream); + return call_int_hook(socket_getpeersec_stream, sock, optval, optlen, + len); } /** @@ -4701,19 +4633,7 @@ int security_socket_getpeersec_stream(struct socket *sock, sockptr_t optval, int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) { - struct security_hook_list *hp; - int rc; - - /* - * Only one module will provide a security context. - */ - hlist_for_each_entry(hp, &security_hook_heads.socket_getpeersec_dgram, - list) { - rc = hp->hook.socket_getpeersec_dgram(sock, skb, secid); - if (rc != LSM_RET_DEFAULT(socket_getpeersec_dgram)) - return rc; - } - return LSM_RET_DEFAULT(socket_getpeersec_dgram); + return call_int_hook(socket_getpeersec_dgram, sock, skb, secid); } EXPORT_SYMBOL(security_socket_getpeersec_dgram); @@ -4730,7 +4650,7 @@ EXPORT_SYMBOL(security_socket_getpeersec_dgram); */ int security_sk_alloc(struct sock *sk, int family, gfp_t priority) { - return call_int_hook(sk_alloc_security, 0, sk, family, priority); + return call_int_hook(sk_alloc_security, sk, family, priority); } /** @@ -4811,7 +4731,7 @@ EXPORT_SYMBOL(security_sock_graft); int security_inet_conn_request(const struct sock *sk, struct sk_buff *skb, struct request_sock *req) { - return call_int_hook(inet_conn_request, 0, sk, skb, req); + return call_int_hook(inet_conn_request, sk, skb, req); } EXPORT_SYMBOL(security_inet_conn_request); @@ -4852,7 +4772,7 @@ EXPORT_SYMBOL(security_inet_conn_established); */ int security_secmark_relabel_packet(u32 secid) { - return call_int_hook(secmark_relabel_packet, 0, secid); + return call_int_hook(secmark_relabel_packet, secid); } EXPORT_SYMBOL(security_secmark_relabel_packet); @@ -4889,7 +4809,7 @@ EXPORT_SYMBOL(security_secmark_refcount_dec); */ int security_tun_dev_alloc_security(void **security) { - return call_int_hook(tun_dev_alloc_security, 0, security); + return call_int_hook(tun_dev_alloc_security, security); } EXPORT_SYMBOL(security_tun_dev_alloc_security); @@ -4914,7 +4834,7 @@ EXPORT_SYMBOL(security_tun_dev_free_security); */ int security_tun_dev_create(void) { - return call_int_hook(tun_dev_create, 0); + return call_int_hook(tun_dev_create); } EXPORT_SYMBOL(security_tun_dev_create); @@ -4928,7 +4848,7 @@ EXPORT_SYMBOL(security_tun_dev_create); */ int security_tun_dev_attach_queue(void *security) { - return call_int_hook(tun_dev_attach_queue, 0, security); + return call_int_hook(tun_dev_attach_queue, security); } EXPORT_SYMBOL(security_tun_dev_attach_queue); @@ -4944,7 +4864,7 @@ EXPORT_SYMBOL(security_tun_dev_attach_queue); */ int security_tun_dev_attach(struct sock *sk, void *security) { - return call_int_hook(tun_dev_attach, 0, sk, security); + return call_int_hook(tun_dev_attach, sk, security); } EXPORT_SYMBOL(security_tun_dev_attach); @@ -4959,7 +4879,7 @@ EXPORT_SYMBOL(security_tun_dev_attach); */ int security_tun_dev_open(void *security) { - return call_int_hook(tun_dev_open, 0, security); + return call_int_hook(tun_dev_open, security); } EXPORT_SYMBOL(security_tun_dev_open); @@ -4975,7 +4895,7 @@ EXPORT_SYMBOL(security_tun_dev_open); int security_sctp_assoc_request(struct sctp_association *asoc, struct sk_buff *skb) { - return call_int_hook(sctp_assoc_request, 0, asoc, skb); + return call_int_hook(sctp_assoc_request, asoc, skb); } EXPORT_SYMBOL(security_sctp_assoc_request); @@ -4996,8 +4916,7 @@ EXPORT_SYMBOL(security_sctp_assoc_request); int security_sctp_bind_connect(struct sock *sk, int optname, struct sockaddr *address, int addrlen) { - return call_int_hook(sctp_bind_connect, 0, sk, optname, - address, addrlen); + return call_int_hook(sctp_bind_connect, sk, optname, address, addrlen); } EXPORT_SYMBOL(security_sctp_bind_connect); @@ -5031,7 +4950,7 @@ EXPORT_SYMBOL(security_sctp_sk_clone); int security_sctp_assoc_established(struct sctp_association *asoc, struct sk_buff *skb) { - return call_int_hook(sctp_assoc_established, 0, asoc, skb); + return call_int_hook(sctp_assoc_established, asoc, skb); } EXPORT_SYMBOL(security_sctp_assoc_established); @@ -5049,7 +4968,7 @@ EXPORT_SYMBOL(security_sctp_assoc_established); */ int security_mptcp_add_subflow(struct sock *sk, struct sock *ssk) { - return call_int_hook(mptcp_add_subflow, 0, sk, ssk); + return call_int_hook(mptcp_add_subflow, sk, ssk); } #endif /* CONFIG_SECURITY_NETWORK */ @@ -5067,7 +4986,7 @@ int security_mptcp_add_subflow(struct sock *sk, struct sock *ssk) */ int security_ib_pkey_access(void *sec, u64 subnet_prefix, u16 pkey) { - return call_int_hook(ib_pkey_access, 0, sec, subnet_prefix, pkey); + return call_int_hook(ib_pkey_access, sec, subnet_prefix, pkey); } EXPORT_SYMBOL(security_ib_pkey_access); @@ -5084,8 +5003,7 @@ EXPORT_SYMBOL(security_ib_pkey_access); int security_ib_endport_manage_subnet(void *sec, const char *dev_name, u8 port_num) { - return call_int_hook(ib_endport_manage_subnet, 0, sec, - dev_name, port_num); + return call_int_hook(ib_endport_manage_subnet, sec, dev_name, port_num); } EXPORT_SYMBOL(security_ib_endport_manage_subnet); @@ -5099,7 +5017,7 @@ EXPORT_SYMBOL(security_ib_endport_manage_subnet); */ int security_ib_alloc_security(void **sec) { - return call_int_hook(ib_alloc_security, 0, sec); + return call_int_hook(ib_alloc_security, sec); } EXPORT_SYMBOL(security_ib_alloc_security); @@ -5132,7 +5050,7 @@ int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx, gfp_t gfp) { - return call_int_hook(xfrm_policy_alloc_security, 0, ctxp, sec_ctx, gfp); + return call_int_hook(xfrm_policy_alloc_security, ctxp, sec_ctx, gfp); } EXPORT_SYMBOL(security_xfrm_policy_alloc); @@ -5149,7 +5067,7 @@ EXPORT_SYMBOL(security_xfrm_policy_alloc); int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctxp) { - return call_int_hook(xfrm_policy_clone_security, 0, old_ctx, new_ctxp); + return call_int_hook(xfrm_policy_clone_security, old_ctx, new_ctxp); } /** @@ -5174,7 +5092,7 @@ EXPORT_SYMBOL(security_xfrm_policy_free); */ int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx) { - return call_int_hook(xfrm_policy_delete_security, 0, ctx); + return call_int_hook(xfrm_policy_delete_security, ctx); } /** @@ -5191,7 +5109,7 @@ int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx) int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) { - return call_int_hook(xfrm_state_alloc, 0, x, sec_ctx); + return call_int_hook(xfrm_state_alloc, x, sec_ctx); } EXPORT_SYMBOL(security_xfrm_state_alloc); @@ -5210,7 +5128,7 @@ EXPORT_SYMBOL(security_xfrm_state_alloc); int security_xfrm_state_alloc_acquire(struct xfrm_state *x, struct xfrm_sec_ctx *polsec, u32 secid) { - return call_int_hook(xfrm_state_alloc_acquire, 0, x, polsec, secid); + return call_int_hook(xfrm_state_alloc_acquire, x, polsec, secid); } /** @@ -5223,7 +5141,7 @@ int security_xfrm_state_alloc_acquire(struct xfrm_state *x, */ int security_xfrm_state_delete(struct xfrm_state *x) { - return call_int_hook(xfrm_state_delete_security, 0, x); + return call_int_hook(xfrm_state_delete_security, x); } EXPORT_SYMBOL(security_xfrm_state_delete); @@ -5252,7 +5170,7 @@ void security_xfrm_state_free(struct xfrm_state *x) */ int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid) { - return call_int_hook(xfrm_policy_lookup, 0, ctx, fl_secid); + return call_int_hook(xfrm_policy_lookup, ctx, fl_secid); } /** @@ -5300,12 +5218,12 @@ int security_xfrm_state_pol_flow_match(struct xfrm_state *x, */ int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid) { - return call_int_hook(xfrm_decode_session, 0, skb, secid, 1); + return call_int_hook(xfrm_decode_session, skb, secid, 1); } void security_skb_classify_flow(struct sk_buff *skb, struct flowi_common *flic) { - int rc = call_int_hook(xfrm_decode_session, 0, skb, &flic->flowic_secid, + int rc = call_int_hook(xfrm_decode_session, skb, &flic->flowic_secid, 0); BUG_ON(rc); @@ -5328,7 +5246,7 @@ EXPORT_SYMBOL(security_skb_classify_flow); int security_key_alloc(struct key *key, const struct cred *cred, unsigned long flags) { - return call_int_hook(key_alloc, 0, key, cred, flags); + return call_int_hook(key_alloc, key, cred, flags); } /** @@ -5355,7 +5273,7 @@ void security_key_free(struct key *key) int security_key_permission(key_ref_t key_ref, const struct cred *cred, enum key_need_perm need_perm) { - return call_int_hook(key_permission, 0, key_ref, cred, need_perm); + return call_int_hook(key_permission, key_ref, cred, need_perm); } /** @@ -5374,7 +5292,7 @@ int security_key_permission(key_ref_t key_ref, const struct cred *cred, int security_key_getsecurity(struct key *key, char **buffer) { *buffer = NULL; - return call_int_hook(key_getsecurity, 0, key, buffer); + return call_int_hook(key_getsecurity, key, buffer); } /** @@ -5412,7 +5330,7 @@ void security_key_post_create_or_update(struct key *keyring, struct key *key, */ int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule) { - return call_int_hook(audit_rule_init, 0, field, op, rulestr, lsmrule); + return call_int_hook(audit_rule_init, field, op, rulestr, lsmrule); } /** @@ -5426,7 +5344,7 @@ int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule) */ int security_audit_rule_known(struct audit_krule *krule) { - return call_int_hook(audit_rule_known, 0, krule); + return call_int_hook(audit_rule_known, krule); } /** @@ -5456,7 +5374,7 @@ void security_audit_rule_free(void *lsmrule) */ int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule) { - return call_int_hook(audit_rule_match, 0, secid, field, op, lsmrule); + return call_int_hook(audit_rule_match, secid, field, op, lsmrule); } #endif /* CONFIG_AUDIT */ @@ -5475,7 +5393,7 @@ int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule) */ int security_bpf(int cmd, union bpf_attr *attr, unsigned int size) { - return call_int_hook(bpf, 0, cmd, attr, size); + return call_int_hook(bpf, cmd, attr, size); } /** @@ -5490,7 +5408,7 @@ int security_bpf(int cmd, union bpf_attr *attr, unsigned int size) */ int security_bpf_map(struct bpf_map *map, fmode_t fmode) { - return call_int_hook(bpf_map, 0, map, fmode); + return call_int_hook(bpf_map, map, fmode); } /** @@ -5504,7 +5422,7 @@ int security_bpf_map(struct bpf_map *map, fmode_t fmode) */ int security_bpf_prog(struct bpf_prog *prog) { - return call_int_hook(bpf_prog, 0, prog); + return call_int_hook(bpf_prog, prog); } /** @@ -5517,7 +5435,7 @@ int security_bpf_prog(struct bpf_prog *prog) */ int security_bpf_map_alloc(struct bpf_map *map) { - return call_int_hook(bpf_map_alloc_security, 0, map); + return call_int_hook(bpf_map_alloc_security, map); } /** @@ -5530,7 +5448,7 @@ int security_bpf_map_alloc(struct bpf_map *map) */ int security_bpf_prog_alloc(struct bpf_prog_aux *aux) { - return call_int_hook(bpf_prog_alloc_security, 0, aux); + return call_int_hook(bpf_prog_alloc_security, aux); } /** @@ -5567,7 +5485,7 @@ void security_bpf_prog_free(struct bpf_prog_aux *aux) */ int security_locked_down(enum lockdown_reason what) { - return call_int_hook(locked_down, 0, what); + return call_int_hook(locked_down, what); } EXPORT_SYMBOL(security_locked_down); @@ -5583,7 +5501,7 @@ EXPORT_SYMBOL(security_locked_down); */ int security_perf_event_open(struct perf_event_attr *attr, int type) { - return call_int_hook(perf_event_open, 0, attr, type); + return call_int_hook(perf_event_open, attr, type); } /** @@ -5596,7 +5514,7 @@ int security_perf_event_open(struct perf_event_attr *attr, int type) */ int security_perf_event_alloc(struct perf_event *event) { - return call_int_hook(perf_event_alloc, 0, event); + return call_int_hook(perf_event_alloc, event); } /** @@ -5620,7 +5538,7 @@ void security_perf_event_free(struct perf_event *event) */ int security_perf_event_read(struct perf_event *event) { - return call_int_hook(perf_event_read, 0, event); + return call_int_hook(perf_event_read, event); } /** @@ -5633,7 +5551,7 @@ int security_perf_event_read(struct perf_event *event) */ int security_perf_event_write(struct perf_event *event) { - return call_int_hook(perf_event_write, 0, event); + return call_int_hook(perf_event_write, event); } #endif /* CONFIG_PERF_EVENTS */ @@ -5649,7 +5567,7 @@ int security_perf_event_write(struct perf_event *event) */ int security_uring_override_creds(const struct cred *new) { - return call_int_hook(uring_override_creds, 0, new); + return call_int_hook(uring_override_creds, new); } /** @@ -5662,7 +5580,7 @@ int security_uring_override_creds(const struct cred *new) */ int security_uring_sqpoll(void) { - return call_int_hook(uring_sqpoll, 0); + return call_int_hook(uring_sqpoll); } /** @@ -5675,6 +5593,6 @@ int security_uring_sqpoll(void) */ int security_uring_cmd(struct io_uring_cmd *ioucmd) { - return call_int_hook(uring_cmd, 0, ioucmd); + return call_int_hook(uring_cmd, ioucmd); } #endif /* CONFIG_IO_URING */ -- cgit v1.2.3 From 2947a4567f3a79127d2d540384e7f042106c1a24 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Tue, 9 Jan 2024 15:16:31 -0700 Subject: treewide: update LLVM Bugzilla links LLVM moved their issue tracker from their own Bugzilla instance to GitHub issues. While all of the links are still valid, they may not necessarily show the most up to date information around the issues, as all updates will occur on GitHub, not Bugzilla. Another complication is that the Bugzilla issue number is not always the same as the GitHub issue number. Thankfully, LLVM maintains this mapping through two shortlinks: https://llvm.org/bz -> https://bugs.llvm.org/show_bug.cgi?id= https://llvm.org/pr -> https://github.com/llvm/llvm-project/issues/ Switch all "https://bugs.llvm.org/show_bug.cgi?id=" links to the "https://llvm.org/pr" shortlink so that the links show the most up to date information. Each migrated issue links back to the Bugzilla entry, so there should be no loss of fidelity of information here. Link: https://lkml.kernel.org/r/20240109-update-llvm-links-v1-3-eb09b59db071@kernel.org Signed-off-by: Nathan Chancellor Reviewed-by: Kees Cook Acked-by: Fangrui Song Cc: Alexei Starovoitov Cc: Andrii Nakryiko Cc: Daniel Borkmann Cc: Mykola Lysenko Signed-off-by: Andrew Morton --- security/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security') diff --git a/security/Kconfig b/security/Kconfig index 52c9af08ad35..606a87c29a01 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -142,7 +142,7 @@ config HARDENED_USERCOPY config FORTIFY_SOURCE bool "Harden common str/mem functions against buffer overflows" depends on ARCH_HAS_FORTIFY_SOURCE - # https://bugs.llvm.org/show_bug.cgi?id=41459 + # https://llvm.org/pr41459 depends on !CC_IS_CLANG || CLANG_VERSION >= 120001 # https://github.com/llvm/llvm-project/issues/53645 depends on !CC_IS_CLANG || !X86_32 -- cgit v1.2.3 From 7d354f49b8d6b29208beb6233ebd197c7570a88b Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Thu, 25 Jan 2024 15:55:15 -0700 Subject: fortify: drop Clang version check for 12.0.1 or newer Now that the minimum supported version of LLVM for building the kernel has been bumped to 13.0.1, this condition is always true, as the build will fail during the configuration stage for older LLVM versions. Remove it. Link: https://lkml.kernel.org/r/20240125-bump-min-llvm-ver-to-13-0-1-v1-9-f5ff9bda41c5@kernel.org Signed-off-by: Nathan Chancellor Reviewed-by: Kees Cook Cc: Albert Ou Cc: "Aneesh Kumar K.V (IBM)" Cc: Ard Biesheuvel Cc: Borislav Petkov (AMD) Cc: Catalin Marinas Cc: Conor Dooley Cc: Dave Hansen Cc: Ingo Molnar Cc: Mark Rutland Cc: Masahiro Yamada Cc: Michael Ellerman Cc: "Naveen N. Rao" Cc: Nicholas Piggin Cc: Nicolas Schier Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Russell King Cc: Thomas Gleixner Cc: Will Deacon Signed-off-by: Andrew Morton --- security/Kconfig | 2 -- 1 file changed, 2 deletions(-) (limited to 'security') diff --git a/security/Kconfig b/security/Kconfig index 606a87c29a01..412e76f1575d 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -142,8 +142,6 @@ config HARDENED_USERCOPY config FORTIFY_SOURCE bool "Harden common str/mem functions against buffer overflows" depends on ARCH_HAS_FORTIFY_SOURCE - # https://llvm.org/pr41459 - depends on !CC_IS_CLANG || CLANG_VERSION >= 120001 # https://github.com/llvm/llvm-project/issues/53645 depends on !CC_IS_CLANG || !X86_32 help -- cgit v1.2.3 From 86dc9693145bc3b2c21d2bc6a2563376ba8b15ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= Date: Fri, 23 Feb 2024 20:05:45 +0100 Subject: selinux: fix lsm_get_self_attr() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit selinux_getselfattr() doesn't properly initialize the string pointer it passes to selinux_lsm_getattr() which can cause a problem when an attribute hasn't been explicitly set; selinux_lsm_getattr() returns 0/success, but does not set or initialize the string label/attribute. Failure to properly initialize the string causes problems later in selinux_getselfattr() when the function attempts to kfree() the string. Cc: Casey Schaufler Fixes: 762c934317e6 ("SELinux: Add selfattr hooks") Suggested-by: Paul Moore [PM: description changes as discussed in the thread] Signed-off-by: Mickaël Salaün Signed-off-by: Paul Moore --- security/selinux/hooks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index a6bf90ace84c..338b023a8c3e 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6559,7 +6559,7 @@ static int selinux_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx, size_t *size, u32 flags) { int rc; - char *val; + char *val = NULL; int val_len; val_len = selinux_lsm_getattr(attr, current, &val); -- cgit v1.2.3 From 6d2fb472ea9ea27f765f10ba65ec73d30f6b7977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= Date: Fri, 23 Feb 2024 20:05:46 +0100 Subject: apparmor: fix lsm_get_self_attr() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In apparmor_getselfattr() when an invalid AppArmor attribute is requested, or a value hasn't been explicitly set for the requested attribute, the label passed to aa_put_label() is not properly initialized which can cause problems when the pointer value is non-NULL and AppArmor attempts to drop a reference on the bogus label object. Cc: Casey Schaufler Cc: John Johansen Fixes: 223981db9baf ("AppArmor: Add selfattr hooks") Signed-off-by: Mickaël Salaün Reviewed-by: Paul Moore [PM: description changes as discussed with MS] Signed-off-by: Paul Moore --- security/apparmor/lsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security') diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 7717354ce095..63df97418b46 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -782,7 +782,7 @@ static int apparmor_getselfattr(unsigned int attr, struct lsm_ctx __user *lx, int error = -ENOENT; struct aa_task_ctx *ctx = task_ctx(current); struct aa_label *label = NULL; - char *value; + char *value = NULL; switch (attr) { case LSM_ATTR_CURRENT: -- cgit v1.2.3 From 954a8ac0ce265ec6880f738959c7bb85d511268e Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 22 Feb 2024 18:52:19 -0500 Subject: selinux: fix style issues in security/selinux/ss/avtab.h As part of on ongoing effort to perform more automated testing and provide more tools for individual developers to validate their patches before submitting, we are trying to make our code "clang-format clean". My hope is that once we have fixed all of our style "quirks", developers will be able to run clang-format on their patches to help avoid silly formatting problems and ensure their changes fit in well with the rest of the SELinux kernel code. Signed-off-by: Paul Moore --- security/selinux/ss/avtab.h | 74 ++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 37 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index 3c3904bf02b0..8e8820484c55 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h @@ -9,42 +9,42 @@ * Author : Stephen Smalley, */ -/* Updated: Frank Mayer and Karl MacMillan - * - * Added conditional policy language extensions - * - * Copyright (C) 2003 Tresys Technology, LLC +/* Updated: Frank Mayer and + * Karl MacMillan + * Added conditional policy language extensions + * Copyright (C) 2003 Tresys Technology, LLC * * Updated: Yuichi Nakamura - * Tuned number of hash slots for avtab to reduce memory usage + * Tuned number of hash slots for avtab to reduce memory usage */ + #ifndef _SS_AVTAB_H_ #define _SS_AVTAB_H_ #include "security.h" struct avtab_key { - u16 source_type; /* source type */ - u16 target_type; /* target type */ - u16 target_class; /* target object class */ -#define AVTAB_ALLOWED 0x0001 -#define AVTAB_AUDITALLOW 0x0002 -#define AVTAB_AUDITDENY 0x0004 -#define AVTAB_AV (AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY) -#define AVTAB_TRANSITION 0x0010 -#define AVTAB_MEMBER 0x0020 -#define AVTAB_CHANGE 0x0040 -#define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE) + u16 source_type; /* source type */ + u16 target_type; /* target type */ + u16 target_class; /* target object class */ +#define AVTAB_ALLOWED 0x0001 +#define AVTAB_AUDITALLOW 0x0002 +#define AVTAB_AUDITDENY 0x0004 +#define AVTAB_AV (AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY) +#define AVTAB_TRANSITION 0x0010 +#define AVTAB_MEMBER 0x0020 +#define AVTAB_CHANGE 0x0040 +#define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE) /* extended permissions */ #define AVTAB_XPERMS_ALLOWED 0x0100 -#define AVTAB_XPERMS_AUDITALLOW 0x0200 +#define AVTAB_XPERMS_AUDITALLOW 0x0200 #define AVTAB_XPERMS_DONTAUDIT 0x0400 -#define AVTAB_XPERMS (AVTAB_XPERMS_ALLOWED | \ - AVTAB_XPERMS_AUDITALLOW | \ - AVTAB_XPERMS_DONTAUDIT) -#define AVTAB_ENABLED_OLD 0x80000000 /* reserved for used in cond_avtab */ -#define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */ - u16 specified; /* what field is specified */ +#define AVTAB_XPERMS \ + (AVTAB_XPERMS_ALLOWED | AVTAB_XPERMS_AUDITALLOW | \ + AVTAB_XPERMS_DONTAUDIT) +#define AVTAB_ENABLED_OLD 0x80000000 /* reserved for used in cond_avtab */ +#define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */ + u16 specified; /* what field is specified */ }; /* @@ -53,8 +53,8 @@ struct avtab_key { */ struct avtab_extended_perms { /* These are not flags. All 256 values may be used */ -#define AVTAB_XPERMS_IOCTLFUNCTION 0x01 -#define AVTAB_XPERMS_IOCTLDRIVER 0x02 +#define AVTAB_XPERMS_IOCTLFUNCTION 0x01 +#define AVTAB_XPERMS_IOCTLDRIVER 0x02 /* extension of the avtab_key specified */ u8 specified; /* ioctl, netfilter, ... */ /* @@ -82,9 +82,9 @@ struct avtab_node { struct avtab { struct avtab_node **htable; - u32 nel; /* number of elements */ - u32 nslot; /* number of hash slots */ - u32 mask; /* mask to compute hash func */ + u32 nel; /* number of elements */ + u32 nslot; /* number of hash slots */ + u32 mask; /* mask to compute hash func */ }; void avtab_init(struct avtab *h); @@ -92,6 +92,9 @@ int avtab_alloc(struct avtab *, u32); int avtab_alloc_dup(struct avtab *new, const struct avtab *orig); void avtab_destroy(struct avtab *h); +#define MAX_AVTAB_HASH_BITS 16 +#define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) + #ifdef CONFIG_SECURITY_SELINUX_DEBUG void avtab_hash_eval(struct avtab *h, const char *tag); #else @@ -107,7 +110,8 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, void *p); int avtab_read(struct avtab *a, void *fp, struct policydb *pol); -int avtab_write_item(struct policydb *p, const struct avtab_node *cur, void *fp); +int avtab_write_item(struct policydb *p, const struct avtab_node *cur, + void *fp); int avtab_write(struct policydb *p, struct avtab *a, void *fp); struct avtab_node *avtab_insert_nonunique(struct avtab *h, @@ -116,11 +120,7 @@ struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_node *avtab_search_node(struct avtab *h, const struct avtab_key *key); +struct avtab_node *avtab_search_node_next(struct avtab_node *node, + u16 specified); -struct avtab_node *avtab_search_node_next(struct avtab_node *node, u16 specified); - -#define MAX_AVTAB_HASH_BITS 16 -#define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) - -#endif /* _SS_AVTAB_H_ */ - +#endif /* _SS_AVTAB_H_ */ -- cgit v1.2.3 From 00ddc59112ec7efd65076503770ab696751c6006 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 22 Feb 2024 18:52:20 -0500 Subject: selinux: fix style issues in security/selinux/ss/avtab.c As part of on ongoing effort to perform more automated testing and provide more tools for individual developers to validate their patches before submitting, we are trying to make our code "clang-format clean". My hope is that once we have fixed all of our style "quirks", developers will be able to run clang-format on their patches to help avoid silly formatting problems and ensure their changes fit in well with the rest of the SELinux kernel code. Signed-off-by: Paul Moore --- security/selinux/ss/avtab.c | 105 +++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 54 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index 697eb4352439..2ad98732d052 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -1,20 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Implementation of the access vector table type. * * Author : Stephen Smalley, */ -/* Updated: Frank Mayer and Karl MacMillan - * - * Added conditional policy language extensions - * - * Copyright (C) 2003 Tresys Technology, LLC - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2. +/* Updated: Frank Mayer and + * Karl MacMillan + * Added conditional policy language extensions + * Copyright (C) 2003 Tresys Technology, LLC * * Updated: Yuichi Nakamura - * Tuned number of hash slots for avtab to reduce memory usage + * Tuned number of hash slots for avtab to reduce memory usage */ #include @@ -36,19 +33,20 @@ static inline u32 avtab_hash(const struct avtab_key *keyp, u32 mask) static const u32 c2 = 0x1b873593; static const u32 r1 = 15; static const u32 r2 = 13; - static const u32 m = 5; - static const u32 n = 0xe6546b64; + static const u32 m = 5; + static const u32 n = 0xe6546b64; u32 hash = 0; -#define mix(input) do { \ - u32 v = input; \ - v *= c1; \ - v = (v << r1) | (v >> (32 - r1)); \ - v *= c2; \ - hash ^= v; \ +#define mix(input) \ + do { \ + u32 v = input; \ + v *= c1; \ + v = (v << r1) | (v >> (32 - r1)); \ + v *= c2; \ + hash ^= v; \ hash = (hash << r2) | (hash >> (32 - r2)); \ - hash = hash * m + n; \ + hash = hash * m + n; \ } while (0) mix(keyp->target_class); @@ -66,9 +64,10 @@ static inline u32 avtab_hash(const struct avtab_key *keyp, u32 mask) return hash & mask; } -static struct avtab_node* -avtab_insert_node(struct avtab *h, struct avtab_node **dst, - const struct avtab_key *key, const struct avtab_datum *datum) +static struct avtab_node *avtab_insert_node(struct avtab *h, + struct avtab_node **dst, + const struct avtab_key *key, + const struct avtab_datum *datum) { struct avtab_node *newnode; struct avtab_extended_perms *xperms; @@ -99,7 +98,7 @@ avtab_insert_node(struct avtab *h, struct avtab_node **dst, static int avtab_node_cmp(const struct avtab_key *key1, const struct avtab_key *key2) { - u16 specified = key1->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); + u16 specified = key1->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD); if (key1->source_type == key2->source_type && key1->target_type == key2->target_type && @@ -129,8 +128,7 @@ static int avtab_insert(struct avtab *h, const struct avtab_key *key, return -EINVAL; hvalue = avtab_hash(key, h->mask); - for (prev = NULL, cur = h->htable[hvalue]; - cur; + for (prev = NULL, cur = h->htable[hvalue]; cur; prev = cur, cur = cur->next) { cmp = avtab_node_cmp(key, &cur->key); /* extended perms may not be unique */ @@ -163,8 +161,7 @@ struct avtab_node *avtab_insert_nonunique(struct avtab *h, if (!h || !h->nslot || h->nel == U32_MAX) return NULL; hvalue = avtab_hash(key, h->mask); - for (prev = NULL, cur = h->htable[hvalue]; - cur; + for (prev = NULL, cur = h->htable[hvalue]; cur; prev = cur, cur = cur->next) { cmp = avtab_node_cmp(key, &cur->key); if (cmp <= 0) @@ -188,8 +185,7 @@ struct avtab_node *avtab_search_node(struct avtab *h, return NULL; hvalue = avtab_hash(key, h->mask); - for (cur = h->htable[hvalue]; cur; - cur = cur->next) { + for (cur = h->htable[hvalue]; cur; cur = cur->next) { cmp = avtab_node_cmp(key, &cur->key); if (cmp == 0) return cur; @@ -199,8 +195,8 @@ struct avtab_node *avtab_search_node(struct avtab *h, return NULL; } -struct avtab_node* -avtab_search_node_next(struct avtab_node *node, u16 specified) +struct avtab_node *avtab_search_node_next(struct avtab_node *node, + u16 specified) { struct avtab_key tmp_key; struct avtab_node *cur; @@ -314,17 +310,19 @@ void avtab_hash_eval(struct avtab *h, const char *tag) if (chain_len > max_chain_len) max_chain_len = chain_len; - chain2_len_sum += (unsigned long long)chain_len * chain_len; + chain2_len_sum += + (unsigned long long)chain_len * chain_len; } } pr_debug("SELinux: %s: %d entries and %d/%d buckets used, " - "longest chain length %d, sum of chain length^2 %llu\n", - tag, h->nel, slots_used, h->nslot, max_chain_len, - chain2_len_sum); + "longest chain length %d, sum of chain length^2 %llu\n", + tag, h->nel, slots_used, h->nslot, max_chain_len, + chain2_len_sum); } #endif /* CONFIG_SECURITY_SELINUX_DEBUG */ +/* clang-format off */ static const uint16_t spec_order[] = { AVTAB_ALLOWED, AVTAB_AUDITDENY, @@ -336,6 +334,7 @@ static const uint16_t spec_order[] = { AVTAB_XPERMS_AUDITALLOW, AVTAB_XPERMS_DONTAUDIT }; +/* clang-format on */ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, int (*insertf)(struct avtab *a, const struct avtab_key *k, @@ -365,9 +364,8 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, if (items2 > ARRAY_SIZE(buf32)) { pr_err("SELinux: avtab: entry overflow\n"); return -EINVAL; - } - rc = next_entry(buf32, fp, sizeof(u32)*items2); + rc = next_entry(buf32, fp, sizeof(u32) * items2); if (rc) { pr_err("SELinux: avtab: truncated entry\n"); return rc; @@ -400,8 +398,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, pr_err("SELinux: avtab: null entry\n"); return -EINVAL; } - if ((val & AVTAB_AV) && - (val & AVTAB_TYPE)) { + if ((val & AVTAB_AV) && (val & AVTAB_TYPE)) { pr_err("SELinux: avtab: entry has both access vectors and types\n"); return -EINVAL; } @@ -428,7 +425,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, return 0; } - rc = next_entry(buf16, fp, sizeof(u16)*4); + rc = next_entry(buf16, fp, sizeof(u16) * 4); if (rc) { pr_err("SELinux: avtab: truncated entry\n"); return rc; @@ -454,10 +451,11 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, } if ((vers < POLICYDB_VERSION_XPERMS_IOCTL) && - (key.specified & AVTAB_XPERMS)) { + (key.specified & AVTAB_XPERMS)) { pr_err("SELinux: avtab: policy version %u does not " - "support extended permissions rules and one " - "was specified\n", vers); + "support extended permissions rules and one " + "was specified\n", + vers); return -EINVAL; } else if (key.specified & AVTAB_XPERMS) { memset(&xperms, 0, sizeof(struct avtab_extended_perms)); @@ -471,7 +469,8 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, pr_err("SELinux: avtab: truncated entry\n"); return rc; } - rc = next_entry(buf32, fp, sizeof(u32)*ARRAY_SIZE(xperms.perms.p)); + rc = next_entry(buf32, fp, + sizeof(u32) * ARRAY_SIZE(xperms.perms.p)); if (rc) { pr_err("SELinux: avtab: truncated entry\n"); return rc; @@ -507,7 +506,6 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol) __le32 buf[1]; u32 nel, i; - rc = next_entry(buf, fp, sizeof(u32)); if (rc < 0) { pr_err("SELinux: avtab: truncated table\n"); @@ -561,7 +559,8 @@ int avtab_write_item(struct policydb *p, const struct avtab_node *cur, void *fp) return rc; if (cur->key.specified & AVTAB_XPERMS) { - rc = put_entry(&cur->datum.u.xperms->specified, sizeof(u8), 1, fp); + rc = put_entry(&cur->datum.u.xperms->specified, sizeof(u8), 1, + fp); if (rc) return rc; rc = put_entry(&cur->datum.u.xperms->driver, sizeof(u8), 1, fp); @@ -570,7 +569,7 @@ int avtab_write_item(struct policydb *p, const struct avtab_node *cur, void *fp) for (i = 0; i < ARRAY_SIZE(cur->datum.u.xperms->perms.p); i++) buf32[i] = cpu_to_le32(cur->datum.u.xperms->perms.p[i]); rc = put_entry(buf32, sizeof(u32), - ARRAY_SIZE(cur->datum.u.xperms->perms.p), fp); + ARRAY_SIZE(cur->datum.u.xperms->perms.p), fp); } else { buf32[0] = cpu_to_le32(cur->datum.u.data); rc = put_entry(buf32, sizeof(u32), 1, fp); @@ -593,8 +592,7 @@ int avtab_write(struct policydb *p, struct avtab *a, void *fp) return rc; for (i = 0; i < a->nslot; i++) { - for (cur = a->htable[i]; cur; - cur = cur->next) { + for (cur = a->htable[i]; cur; cur = cur->next) { rc = avtab_write_item(p, cur, fp); if (rc) return rc; @@ -606,10 +604,9 @@ int avtab_write(struct policydb *p, struct avtab *a, void *fp) void __init avtab_cache_init(void) { - avtab_node_cachep = kmem_cache_create("avtab_node", - sizeof(struct avtab_node), - 0, SLAB_PANIC, NULL); - avtab_xperms_cachep = kmem_cache_create("avtab_extended_perms", - sizeof(struct avtab_extended_perms), - 0, SLAB_PANIC, NULL); + avtab_node_cachep = kmem_cache_create( + "avtab_node", sizeof(struct avtab_node), 0, SLAB_PANIC, NULL); + avtab_xperms_cachep = kmem_cache_create( + "avtab_extended_perms", sizeof(struct avtab_extended_perms), 0, + SLAB_PANIC, NULL); } -- cgit v1.2.3 From 1602a6c2ecd2bd15037c9016a178d1e0ee4bea23 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 22 Feb 2024 18:52:21 -0500 Subject: selinux: fix style issues in security/selinux/ss/conditional.h As part of on ongoing effort to perform more automated testing and provide more tools for individual developers to validate their patches before submitting, we are trying to make our code "clang-format clean". My hope is that once we have fixed all of our style "quirks", developers will be able to run clang-format on their patches to help avoid silly formatting problems and ensure their changes fit in well with the rest of the SELinux kernel code. Signed-off-by: Paul Moore --- security/selinux/ss/conditional.h | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/conditional.h b/security/selinux/ss/conditional.h index 5a7b51278dc6..b972ce40db18 100644 --- a/security/selinux/ss/conditional.h +++ b/security/selinux/ss/conditional.h @@ -1,8 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* Authors: Karl MacMillan * Frank Mayer - * - * Copyright (C) 2003 - 2004 Tresys Technology, LLC + * Copyright (C) 2003 - 2004 Tresys Technology, LLC */ #ifndef _CONDITIONAL_H_ @@ -20,14 +19,14 @@ * in reverse polish notation. */ struct cond_expr_node { -#define COND_BOOL 1 /* plain bool */ -#define COND_NOT 2 /* !bool */ -#define COND_OR 3 /* bool || bool */ -#define COND_AND 4 /* bool && bool */ -#define COND_XOR 5 /* bool ^ bool */ -#define COND_EQ 6 /* bool == bool */ -#define COND_NEQ 7 /* bool != bool */ -#define COND_LAST COND_NEQ +#define COND_BOOL 1 /* plain bool */ +#define COND_NOT 2 /* !bool */ +#define COND_OR 3 /* bool || bool */ +#define COND_AND 4 /* bool && bool */ +#define COND_XOR 5 /* bool ^ bool */ +#define COND_EQ 6 /* bool == bool */ +#define COND_NEQ 7 /* bool != bool */ +#define COND_LAST COND_NEQ u32 expr_type; u32 boolean; }; @@ -75,9 +74,9 @@ int cond_write_bool(void *key, void *datum, void *ptr); int cond_write_list(struct policydb *p, void *fp); void cond_compute_av(struct avtab *ctab, struct avtab_key *key, - struct av_decision *avd, struct extended_perms *xperms); + struct av_decision *avd, struct extended_perms *xperms); void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key, - struct extended_perms_decision *xpermd); + struct extended_perms_decision *xpermd); void evaluate_cond_nodes(struct policydb *p); void cond_policydb_destroy_dup(struct policydb *p); int cond_policydb_dup(struct policydb *new, struct policydb *orig); -- cgit v1.2.3 From ade6a96f129aa08dfe4630bdd07b932f612cb899 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 22 Feb 2024 18:52:22 -0500 Subject: selinux: fix style issues in security/selinux/ss/conditional.c As part of on ongoing effort to perform more automated testing and provide more tools for individual developers to validate their patches before submitting, we are trying to make our code "clang-format clean". My hope is that once we have fixed all of our style "quirks", developers will be able to run clang-format on their patches to help avoid silly formatting problems and ensure their changes fit in well with the rest of the SELinux kernel code. Signed-off-by: Paul Moore --- security/selinux/ss/conditional.c | 68 +++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 35 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index 81ff676f209a..f12476855b27 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c @@ -1,8 +1,7 @@ -// SPDX-License-Identifier: GPL-2.0-only +/* SPDX-License-Identifier: GPL-2.0-only */ /* Authors: Karl MacMillan * Frank Mayer - * - * Copyright (C) 2003 - 2004 Tresys Technology, LLC + * Copyright (C) 2003 - 2004 Tresys Technology, LLC */ #include @@ -166,9 +165,8 @@ void cond_policydb_destroy(struct policydb *p) int cond_init_bool_indexes(struct policydb *p) { kfree(p->bool_val_to_struct); - p->bool_val_to_struct = kmalloc_array(p->p_bools.nprim, - sizeof(*p->bool_val_to_struct), - GFP_KERNEL); + p->bool_val_to_struct = kmalloc_array( + p->p_bools.nprim, sizeof(*p->bool_val_to_struct), GFP_KERNEL); if (!p->bool_val_to_struct) return -ENOMEM; return 0; @@ -287,7 +285,8 @@ static int cond_insertf(struct avtab *a, const struct avtab_key *k, if (other) { node_ptr = avtab_search_node(&p->te_cond_avtab, k); if (node_ptr) { - if (avtab_search_node_next(node_ptr, k->specified)) { + if (avtab_search_node_next(node_ptr, + k->specified)) { pr_err("SELinux: too many conflicting type rules.\n"); return -EINVAL; } @@ -478,8 +477,8 @@ int cond_write_bool(void *vkey, void *datum, void *ptr) * the conditional. This means that the avtab with the conditional * rules will not be saved but will be rebuilt on policy load. */ -static int cond_write_av_list(struct policydb *p, - struct cond_av_list *list, struct policy_file *fp) +static int cond_write_av_list(struct policydb *p, struct cond_av_list *list, + struct policy_file *fp) { __le32 buf[1]; u32 i; @@ -500,7 +499,7 @@ static int cond_write_av_list(struct policydb *p, } static int cond_write_node(struct policydb *p, struct cond_node *node, - struct policy_file *fp) + struct policy_file *fp) { __le32 buf[2]; int rc; @@ -555,7 +554,7 @@ int cond_write_list(struct policydb *p, void *fp) } void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key, - struct extended_perms_decision *xpermd) + struct extended_perms_decision *xpermd) { struct avtab_node *node; @@ -563,7 +562,7 @@ void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key, return; for (node = avtab_search_node(ctab, key); node; - node = avtab_search_node_next(node, key->specified)) { + node = avtab_search_node_next(node, key->specified)) { if (node->key.specified & AVTAB_ENABLED) services_compute_xperms_decision(xpermd, node); } @@ -572,7 +571,7 @@ void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key, * av table, and if so, add them to the result */ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, - struct av_decision *avd, struct extended_perms *xperms) + struct av_decision *avd, struct extended_perms *xperms) { struct avtab_node *node; @@ -580,30 +579,29 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, return; for (node = avtab_search_node(ctab, key); node; - node = avtab_search_node_next(node, key->specified)) { - if ((u16)(AVTAB_ALLOWED|AVTAB_ENABLED) == - (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) + node = avtab_search_node_next(node, key->specified)) { + if ((u16)(AVTAB_ALLOWED | AVTAB_ENABLED) == + (node->key.specified & (AVTAB_ALLOWED | AVTAB_ENABLED))) avd->allowed |= node->datum.u.data; - if ((u16)(AVTAB_AUDITDENY|AVTAB_ENABLED) == - (node->key.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED))) + if ((u16)(AVTAB_AUDITDENY | AVTAB_ENABLED) == + (node->key.specified & (AVTAB_AUDITDENY | AVTAB_ENABLED))) /* Since a '0' in an auditdeny mask represents a * permission we do NOT want to audit (dontaudit), we use * the '&' operand to ensure that all '0's in the mask * are retained (much unlike the allow and auditallow cases). */ avd->auditdeny &= node->datum.u.data; - if ((u16)(AVTAB_AUDITALLOW|AVTAB_ENABLED) == - (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED))) + if ((u16)(AVTAB_AUDITALLOW | AVTAB_ENABLED) == + (node->key.specified & (AVTAB_AUDITALLOW | AVTAB_ENABLED))) avd->auditallow |= node->datum.u.data; if (xperms && (node->key.specified & AVTAB_ENABLED) && - (node->key.specified & AVTAB_XPERMS)) + (node->key.specified & AVTAB_XPERMS)) services_compute_xperms_drivers(xperms, node); } } -static int cond_dup_av_list(struct cond_av_list *new, - struct cond_av_list *orig, - struct avtab *avtab) +static int cond_dup_av_list(struct cond_av_list *new, struct cond_av_list *orig, + struct avtab *avtab) { u32 i; @@ -614,9 +612,8 @@ static int cond_dup_av_list(struct cond_av_list *new, return -ENOMEM; for (i = 0; i < orig->len; i++) { - new->nodes[i] = avtab_insert_nonunique(avtab, - &orig->nodes[i]->key, - &orig->nodes[i]->datum); + new->nodes[i] = avtab_insert_nonunique( + avtab, &orig->nodes[i]->key, &orig->nodes[i]->datum); if (!new->nodes[i]) return -ENOMEM; new->len++; @@ -637,8 +634,7 @@ static int duplicate_policydb_cond_list(struct policydb *newp, newp->cond_list_len = 0; newp->cond_list = kcalloc(origp->cond_list_len, - sizeof(*newp->cond_list), - GFP_KERNEL); + sizeof(*newp->cond_list), GFP_KERNEL); if (!newp->cond_list) goto error; @@ -649,7 +645,8 @@ static int duplicate_policydb_cond_list(struct policydb *newp, newp->cond_list_len++; newn->cur_state = orign->cur_state; - newn->expr.nodes = kmemdup(orign->expr.nodes, + newn->expr.nodes = + kmemdup(orign->expr.nodes, orign->expr.len * sizeof(*orign->expr.nodes), GFP_KERNEL); if (!newn->expr.nodes) @@ -658,12 +655,12 @@ static int duplicate_policydb_cond_list(struct policydb *newp, newn->expr.len = orign->expr.len; rc = cond_dup_av_list(&newn->true_list, &orign->true_list, - &newp->te_cond_avtab); + &newp->te_cond_avtab); if (rc) goto error; rc = cond_dup_av_list(&newn->false_list, &orign->false_list, - &newp->te_cond_avtab); + &newp->te_cond_avtab); if (rc) goto error; } @@ -683,7 +680,8 @@ static int cond_bools_destroy(void *key, void *datum, void *args) return 0; } -static int cond_bools_copy(struct hashtab_node *new, struct hashtab_node *orig, void *args) +static int cond_bools_copy(struct hashtab_node *new, struct hashtab_node *orig, + void *args) { struct cond_bool_datum *datum; @@ -709,7 +707,7 @@ static int cond_bools_index(void *key, void *datum, void *args) } static int duplicate_policydb_bools(struct policydb *newdb, - struct policydb *orig) + struct policydb *orig) { struct cond_bool_datum **cond_bool_array; int rc; @@ -721,7 +719,7 @@ static int duplicate_policydb_bools(struct policydb *newdb, return -ENOMEM; rc = hashtab_duplicate(&newdb->p_bools.table, &orig->p_bools.table, - cond_bools_copy, cond_bools_destroy, NULL); + cond_bools_copy, cond_bools_destroy, NULL); if (rc) { kfree(cond_bool_array); return -ENOMEM; -- cgit v1.2.3 From e6162e4c3ff9c3f64394480589432621aa96269b Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 22 Feb 2024 18:52:23 -0500 Subject: selinux: fix style issues in security/selinux/ss/constraint.h As part of on ongoing effort to perform more automated testing and provide more tools for individual developers to validate their patches before submitting, we are trying to make our code "clang-format clean". My hope is that once we have fixed all of our style "quirks", developers will be able to run clang-format on their patches to help avoid silly formatting problems and ensure their changes fit in well with the rest of the SELinux kernel code. Signed-off-by: Paul Moore --- security/selinux/ss/constraint.h | 67 ++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 33 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/constraint.h b/security/selinux/ss/constraint.h index f76eb3128ad5..203033cfad67 100644 --- a/security/selinux/ss/constraint.h +++ b/security/selinux/ss/constraint.h @@ -13,6 +13,7 @@ * * Author : Stephen Smalley, */ + #ifndef _SS_CONSTRAINT_H_ #define _SS_CONSTRAINT_H_ @@ -21,43 +22,43 @@ #define CEXPR_MAXDEPTH 5 struct constraint_expr { -#define CEXPR_NOT 1 /* not expr */ -#define CEXPR_AND 2 /* expr and expr */ -#define CEXPR_OR 3 /* expr or expr */ -#define CEXPR_ATTR 4 /* attr op attr */ -#define CEXPR_NAMES 5 /* attr op names */ - u32 expr_type; /* expression type */ - -#define CEXPR_USER 1 /* user */ -#define CEXPR_ROLE 2 /* role */ -#define CEXPR_TYPE 4 /* type */ -#define CEXPR_TARGET 8 /* target if set, source otherwise */ -#define CEXPR_XTARGET 16 /* special 3rd target for validatetrans rule */ -#define CEXPR_L1L2 32 /* low level 1 vs. low level 2 */ -#define CEXPR_L1H2 64 /* low level 1 vs. high level 2 */ -#define CEXPR_H1L2 128 /* high level 1 vs. low level 2 */ -#define CEXPR_H1H2 256 /* high level 1 vs. high level 2 */ -#define CEXPR_L1H1 512 /* low level 1 vs. high level 1 */ -#define CEXPR_L2H2 1024 /* low level 2 vs. high level 2 */ - u32 attr; /* attribute */ - -#define CEXPR_EQ 1 /* == or eq */ -#define CEXPR_NEQ 2 /* != */ -#define CEXPR_DOM 3 /* dom */ -#define CEXPR_DOMBY 4 /* domby */ -#define CEXPR_INCOMP 5 /* incomp */ - u32 op; /* operator */ - - struct ebitmap names; /* names */ +#define CEXPR_NOT 1 /* not expr */ +#define CEXPR_AND 2 /* expr and expr */ +#define CEXPR_OR 3 /* expr or expr */ +#define CEXPR_ATTR 4 /* attr op attr */ +#define CEXPR_NAMES 5 /* attr op names */ + u32 expr_type; /* expression type */ + +#define CEXPR_USER 1 /* user */ +#define CEXPR_ROLE 2 /* role */ +#define CEXPR_TYPE 4 /* type */ +#define CEXPR_TARGET 8 /* target if set, source otherwise */ +#define CEXPR_XTARGET 16 /* special 3rd target for validatetrans rule */ +#define CEXPR_L1L2 32 /* low level 1 vs. low level 2 */ +#define CEXPR_L1H2 64 /* low level 1 vs. high level 2 */ +#define CEXPR_H1L2 128 /* high level 1 vs. low level 2 */ +#define CEXPR_H1H2 256 /* high level 1 vs. high level 2 */ +#define CEXPR_L1H1 512 /* low level 1 vs. high level 1 */ +#define CEXPR_L2H2 1024 /* low level 2 vs. high level 2 */ + u32 attr; /* attribute */ + +#define CEXPR_EQ 1 /* == or eq */ +#define CEXPR_NEQ 2 /* != */ +#define CEXPR_DOM 3 /* dom */ +#define CEXPR_DOMBY 4 /* domby */ +#define CEXPR_INCOMP 5 /* incomp */ + u32 op; /* operator */ + + struct ebitmap names; /* names */ struct type_set *type_names; - struct constraint_expr *next; /* next expression */ + struct constraint_expr *next; /* next expression */ }; struct constraint_node { - u32 permissions; /* constrained permissions */ - struct constraint_expr *expr; /* constraint on permissions */ - struct constraint_node *next; /* next constraint */ + u32 permissions; /* constrained permissions */ + struct constraint_expr *expr; /* constraint on permissions */ + struct constraint_node *next; /* next constraint */ }; -#endif /* _SS_CONSTRAINT_H_ */ +#endif /* _SS_CONSTRAINT_H_ */ -- cgit v1.2.3 From b27e564c09e05fb483c8960831c644de69c79de6 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 22 Feb 2024 18:52:24 -0500 Subject: selinux: fix style issues in security/selinux/ss/context.h As part of on ongoing effort to perform more automated testing and provide more tools for individual developers to validate their patches before submitting, we are trying to make our code "clang-format clean". My hope is that once we have fixed all of our style "quirks", developers will be able to run clang-format on their patches to help avoid silly formatting problems and ensure their changes fit in well with the rest of the SELinux kernel code. Signed-off-by: Paul Moore --- security/selinux/ss/context.h | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h index 1f59468c0759..7ccab2e6965f 100644 --- a/security/selinux/ss/context.h +++ b/security/selinux/ss/context.h @@ -13,6 +13,7 @@ * * Author : Stephen Smalley, */ + #ifndef _SS_CONTEXT_H_ #define _SS_CONTEXT_H_ @@ -28,9 +29,9 @@ struct context { u32 user; u32 role; u32 type; - u32 len; /* length of string in bytes */ + u32 len; /* length of string in bytes */ struct mls_range range; - char *str; /* string representation if context cannot be mapped. */ + char *str; /* string representation if context cannot be mapped. */ }; static inline void mls_context_init(struct context *c) @@ -38,7 +39,8 @@ static inline void mls_context_init(struct context *c) memset(&c->range, 0, sizeof(c->range)); } -static inline int mls_context_cpy(struct context *dst, const struct context *src) +static inline int mls_context_cpy(struct context *dst, + const struct context *src) { int rc; @@ -58,7 +60,8 @@ out: /* * Sets both levels in the MLS range of 'dst' to the low level of 'src'. */ -static inline int mls_context_cpy_low(struct context *dst, const struct context *src) +static inline int mls_context_cpy_low(struct context *dst, + const struct context *src) { int rc; @@ -78,7 +81,8 @@ out: /* * Sets both levels in the MLS range of 'dst' to the high level of 'src'. */ -static inline int mls_context_cpy_high(struct context *dst, const struct context *src) +static inline int mls_context_cpy_high(struct context *dst, + const struct context *src) { int rc; @@ -95,9 +99,9 @@ out: return rc; } - static inline int mls_context_glblub(struct context *dst, - const struct context *c1, const struct context *c2) + const struct context *c1, + const struct context *c2) { struct mls_range *dr = &dst->range; const struct mls_range *r1 = &c1->range, *r2 = &c2->range; @@ -114,13 +118,13 @@ static inline int mls_context_glblub(struct context *dst, /* Take the least of the high */ dr->level[1].sens = min(r1->level[1].sens, r2->level[1].sens); - rc = ebitmap_and(&dr->level[0].cat, - &r1->level[0].cat, &r2->level[0].cat); + rc = ebitmap_and(&dr->level[0].cat, &r1->level[0].cat, + &r2->level[0].cat); if (rc) goto out; - rc = ebitmap_and(&dr->level[1].cat, - &r1->level[1].cat, &r2->level[1].cat); + rc = ebitmap_and(&dr->level[1].cat, &r1->level[1].cat, + &r2->level[1].cat); if (rc) goto out; @@ -128,7 +132,8 @@ out: return rc; } -static inline int mls_context_cmp(const struct context *c1, const struct context *c2) +static inline int mls_context_cmp(const struct context *c1, + const struct context *c2) { return ((c1->range.level[0].sens == c2->range.level[0].sens) && ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) && @@ -183,19 +188,17 @@ static inline void context_destroy(struct context *c) mls_context_destroy(c); } -static inline int context_cmp(const struct context *c1, const struct context *c2) +static inline int context_cmp(const struct context *c1, + const struct context *c2) { if (c1->len && c2->len) return (c1->len == c2->len && !strcmp(c1->str, c2->str)); if (c1->len || c2->len) return 0; - return ((c1->user == c2->user) && - (c1->role == c2->role) && - (c1->type == c2->type) && - mls_context_cmp(c1, c2)); + return ((c1->user == c2->user) && (c1->role == c2->role) && + (c1->type == c2->type) && mls_context_cmp(c1, c2)); } u32 context_compute_hash(const struct context *c); -#endif /* _SS_CONTEXT_H_ */ - +#endif /* _SS_CONTEXT_H_ */ -- cgit v1.2.3 From 05363a7f7dd3cbe87a2d7908445e268e74e51854 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 22 Feb 2024 18:52:25 -0500 Subject: selinux: fix style issues in security/selinux/ss/context.h As part of on ongoing effort to perform more automated testing and provide more tools for individual developers to validate their patches before submitting, we are trying to make our code "clang-format clean". My hope is that once we have fixed all of our style "quirks", developers will be able to run clang-format on their patches to help avoid silly formatting problems and ensure their changes fit in well with the rest of the SELinux kernel code. Signed-off-by: Paul Moore --- security/selinux/ss/context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security') diff --git a/security/selinux/ss/context.c b/security/selinux/ss/context.c index 38bc0aa524a6..e39990f494dd 100644 --- a/security/selinux/ss/context.c +++ b/security/selinux/ss/context.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Implementations of the security context functions. * -- cgit v1.2.3 From 3ec3a835acdfe2a499ff6afdfdd55cc5ac2e4f9b Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 22 Feb 2024 18:52:26 -0500 Subject: selinux: fix style issues in security/selinux/ss/ebitmap.h As part of on ongoing effort to perform more automated testing and provide more tools for individual developers to validate their patches before submitting, we are trying to make our code "clang-format clean". My hope is that once we have fixed all of our style "quirks", developers will be able to run clang-format on their patches to help avoid silly formatting problems and ensure their changes fit in well with the rest of the SELinux kernel code. Signed-off-by: Paul Moore --- security/selinux/ss/ebitmap.h | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h index e3c807cfad90..02798b35eecc 100644 --- a/security/selinux/ss/ebitmap.h +++ b/security/selinux/ss/ebitmap.h @@ -12,23 +12,25 @@ * * Author : Stephen Smalley, */ + #ifndef _SS_EBITMAP_H_ #define _SS_EBITMAP_H_ #include #ifdef CONFIG_64BIT -#define EBITMAP_NODE_SIZE 64 +#define EBITMAP_NODE_SIZE 64 #else -#define EBITMAP_NODE_SIZE 32 +#define EBITMAP_NODE_SIZE 32 #endif -#define EBITMAP_UNIT_NUMS ((EBITMAP_NODE_SIZE-sizeof(void *)-sizeof(u32))\ - / sizeof(unsigned long)) -#define EBITMAP_UNIT_SIZE BITS_PER_LONG -#define EBITMAP_SIZE (EBITMAP_UNIT_NUMS * EBITMAP_UNIT_SIZE) -#define EBITMAP_BIT 1ULL -#define EBITMAP_SHIFT_UNIT_SIZE(x) \ +#define EBITMAP_UNIT_NUMS \ + ((EBITMAP_NODE_SIZE - sizeof(void *) - sizeof(u32)) / \ + sizeof(unsigned long)) +#define EBITMAP_UNIT_SIZE BITS_PER_LONG +#define EBITMAP_SIZE (EBITMAP_UNIT_NUMS * EBITMAP_UNIT_SIZE) +#define EBITMAP_BIT 1ULL +#define EBITMAP_SHIFT_UNIT_SIZE(x) \ (((x) >> EBITMAP_UNIT_SIZE / 2) >> EBITMAP_UNIT_SIZE / 2) struct ebitmap_node { @@ -38,8 +40,8 @@ struct ebitmap_node { }; struct ebitmap { - struct ebitmap_node *node; /* first node in the bitmap */ - u32 highbit; /* highest position in the total bitmap */ + struct ebitmap_node *node; /* first node in the bitmap */ + u32 highbit; /* highest position in the total bitmap */ }; #define ebitmap_length(e) ((e)->highbit) @@ -80,9 +82,9 @@ static inline unsigned int ebitmap_next_positive(const struct ebitmap *e, return ebitmap_length(e); } -#define EBITMAP_NODE_INDEX(node, bit) \ +#define EBITMAP_NODE_INDEX(node, bit) \ (((bit) - (node)->startbit) / EBITMAP_UNIT_SIZE) -#define EBITMAP_NODE_OFFSET(node, bit) \ +#define EBITMAP_NODE_OFFSET(node, bit) \ (((bit) - (node)->startbit) % EBITMAP_UNIT_SIZE) static inline int ebitmap_node_get_bit(const struct ebitmap_node *n, @@ -117,15 +119,17 @@ static inline void ebitmap_node_clr_bit(struct ebitmap_node *n, n->maps[index] &= ~(EBITMAP_BIT << ofs); } -#define ebitmap_for_each_positive_bit(e, n, bit) \ - for ((bit) = ebitmap_start_positive(e, &(n)); \ - (bit) < ebitmap_length(e); \ - (bit) = ebitmap_next_positive(e, &(n), bit)) \ +#define ebitmap_for_each_positive_bit(e, n, bit) \ + for ((bit) = ebitmap_start_positive(e, &(n)); \ + (bit) < ebitmap_length(e); \ + (bit) = ebitmap_next_positive(e, &(n), bit)) int ebitmap_cmp(const struct ebitmap *e1, const struct ebitmap *e2); int ebitmap_cpy(struct ebitmap *dst, const struct ebitmap *src); -int ebitmap_and(struct ebitmap *dst, const struct ebitmap *e1, const struct ebitmap *e2); -int ebitmap_contains(const struct ebitmap *e1, const struct ebitmap *e2, u32 last_e2bit); +int ebitmap_and(struct ebitmap *dst, const struct ebitmap *e1, + const struct ebitmap *e2); +int ebitmap_contains(const struct ebitmap *e1, const struct ebitmap *e2, + u32 last_e2bit); int ebitmap_get_bit(const struct ebitmap *e, unsigned long bit); int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value); void ebitmap_destroy(struct ebitmap *e); @@ -151,4 +155,4 @@ static inline int ebitmap_netlbl_import(struct ebitmap *ebmap, } #endif -#endif /* _SS_EBITMAP_H_ */ +#endif /* _SS_EBITMAP_H_ */ -- cgit v1.2.3 From e951485f7419e73bcb4fd370825cceae53cf9712 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 22 Feb 2024 18:52:27 -0500 Subject: selinux: fix style issues in security/selinux/ss/ebitmap.c As part of on ongoing effort to perform more automated testing and provide more tools for individual developers to validate their patches before submitting, we are trying to make our code "clang-format clean". My hope is that once we have fixed all of our style "quirks", developers will be able to run clang-format on their patches to help avoid silly formatting problems and ensure their changes fit in well with the rest of the SELinux kernel code. Signed-off-by: Paul Moore --- security/selinux/ss/ebitmap.c | 56 +++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index 77875ad355f7..67c1a73cd5ee 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Implementation of the extensible bitmap type. * @@ -6,14 +6,11 @@ */ /* * Updated: Hewlett-Packard + * Added support to import/export the NetLabel category bitmap + * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 * - * Added support to import/export the NetLabel category bitmap - * - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - */ -/* * Updated: KaiGai Kohei - * Applied standard bit operations to improve bitmap scanning. + * Applied standard bit operations to improve bitmap scanning. */ #include @@ -24,7 +21,7 @@ #include "ebitmap.h" #include "policydb.h" -#define BITS_PER_U64 (sizeof(u64) * 8) +#define BITS_PER_U64 (sizeof(u64) * 8) static struct kmem_cache *ebitmap_node_cachep __ro_after_init; @@ -37,8 +34,7 @@ int ebitmap_cmp(const struct ebitmap *e1, const struct ebitmap *e2) n1 = e1->node; n2 = e2->node; - while (n1 && n2 && - (n1->startbit == n2->startbit) && + while (n1 && n2 && (n1->startbit == n2->startbit) && !memcmp(n1->maps, n2->maps, EBITMAP_SIZE / 8)) { n1 = n1->next; n2 = n2->next; @@ -79,14 +75,16 @@ int ebitmap_cpy(struct ebitmap *dst, const struct ebitmap *src) return 0; } -int ebitmap_and(struct ebitmap *dst, const struct ebitmap *e1, const struct ebitmap *e2) +int ebitmap_and(struct ebitmap *dst, const struct ebitmap *e1, + const struct ebitmap *e2) { struct ebitmap_node *n; int bit, rc; ebitmap_init(dst); - ebitmap_for_each_positive_bit(e1, n, bit) { + ebitmap_for_each_positive_bit(e1, n, bit) + { if (ebitmap_get_bit(e2, bit)) { rc = ebitmap_set_bit(dst, bit, 1); if (rc < 0) @@ -96,7 +94,6 @@ int ebitmap_and(struct ebitmap *dst, const struct ebitmap *e1, const struct ebit return 0; } - #ifdef CONFIG_NETLABEL /** * ebitmap_netlbl_export - Export an ebitmap into a NetLabel category bitmap @@ -131,10 +128,8 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap, for (iter = 0; iter < EBITMAP_UNIT_NUMS; iter++) { e_map = e_iter->maps[iter]; if (e_map != 0) { - rc = netlbl_catmap_setlong(catmap, - offset, - e_map, - GFP_ATOMIC); + rc = netlbl_catmap_setlong(catmap, offset, + e_map, GFP_ATOMIC); if (rc != 0) goto netlbl_export_failure; } @@ -185,7 +180,8 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap, if (e_iter == NULL || offset >= e_iter->startbit + EBITMAP_SIZE) { e_prev = e_iter; - e_iter = kmem_cache_zalloc(ebitmap_node_cachep, GFP_ATOMIC); + e_iter = kmem_cache_zalloc(ebitmap_node_cachep, + GFP_ATOMIC); if (e_iter == NULL) goto netlbl_import_failure; e_iter->startbit = offset - (offset % EBITMAP_SIZE); @@ -218,7 +214,8 @@ netlbl_import_failure: * if last_e2bit is non-zero, the highest set bit in e2 cannot exceed * last_e2bit. */ -int ebitmap_contains(const struct ebitmap *e1, const struct ebitmap *e2, u32 last_e2bit) +int ebitmap_contains(const struct ebitmap *e1, const struct ebitmap *e2, + u32 last_e2bit) { const struct ebitmap_node *n1, *n2; int i; @@ -234,8 +231,8 @@ int ebitmap_contains(const struct ebitmap *e1, const struct ebitmap *e2, u32 las n1 = n1->next; continue; } - for (i = EBITMAP_UNIT_NUMS - 1; (i >= 0) && !n2->maps[i]; ) - i--; /* Skip trailing NULL map entries */ + for (i = EBITMAP_UNIT_NUMS - 1; (i >= 0) && !n2->maps[i];) + i--; /* Skip trailing NULL map entries */ if (last_e2bit && (i >= 0)) { u32 lastsetbit = n2->startbit + i * EBITMAP_UNIT_SIZE + __fls(n2->maps[i]); @@ -302,8 +299,8 @@ int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value) * within the bitmap */ if (prev) - e->highbit = prev->startbit - + EBITMAP_SIZE; + e->highbit = prev->startbit + + EBITMAP_SIZE; else e->highbit = 0; } @@ -424,7 +421,8 @@ int ebitmap_read(struct ebitmap *e, void *fp) if (!n || startbit >= n->startbit + EBITMAP_SIZE) { struct ebitmap_node *tmp; - tmp = kmem_cache_zalloc(ebitmap_node_cachep, GFP_KERNEL); + tmp = kmem_cache_zalloc(ebitmap_node_cachep, + GFP_KERNEL); if (!tmp) { pr_err("SELinux: ebitmap: out of memory\n"); rc = -ENOMEM; @@ -481,7 +479,8 @@ int ebitmap_write(const struct ebitmap *e, void *fp) count = 0; last_bit = 0; last_startbit = -1; - ebitmap_for_each_positive_bit(e, n, bit) { + ebitmap_for_each_positive_bit(e, n, bit) + { if (rounddown(bit, (int)BITS_PER_U64) > last_startbit) { count++; last_startbit = rounddown(bit, BITS_PER_U64); @@ -497,7 +496,8 @@ int ebitmap_write(const struct ebitmap *e, void *fp) map = 0; last_startbit = INT_MIN; - ebitmap_for_each_positive_bit(e, n, bit) { + ebitmap_for_each_positive_bit(e, n, bit) + { if (rounddown(bit, (int)BITS_PER_U64) > last_startbit) { __le64 buf64[1]; @@ -559,6 +559,6 @@ u32 ebitmap_hash(const struct ebitmap *e, u32 hash) void __init ebitmap_cache_init(void) { ebitmap_node_cachep = kmem_cache_create("ebitmap_node", - sizeof(struct ebitmap_node), - 0, SLAB_PANIC, NULL); + sizeof(struct ebitmap_node), 0, + SLAB_PANIC, NULL); } -- cgit v1.2.3 From a84f5aa628321ece019e5d3e02b54cbd782b22dd Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 22 Feb 2024 18:52:28 -0500 Subject: selinux: fix style issues in security/selinux/ss/hashtab.h As part of on ongoing effort to perform more automated testing and provide more tools for individual developers to validate their patches before submitting, we are trying to make our code "clang-format clean". My hope is that once we have fixed all of our style "quirks", developers will be able to run clang-format on their patches to help avoid silly formatting problems and ensure their changes fit in well with the rest of the SELinux kernel code. Signed-off-by: Paul Moore --- security/selinux/ss/hashtab.h | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/hashtab.h b/security/selinux/ss/hashtab.h index 09b0a3744937..5f74dcc1360f 100644 --- a/security/selinux/ss/hashtab.h +++ b/security/selinux/ss/hashtab.h @@ -8,6 +8,7 @@ * * Author : Stephen Smalley, */ + #ifndef _SS_HASHTAB_H_ #define _SS_HASHTAB_H_ @@ -15,12 +16,11 @@ #include #include -#define HASHTAB_MAX_NODES U32_MAX +#define HASHTAB_MAX_NODES U32_MAX struct hashtab_key_params { - u32 (*hash)(const void *key); /* hash function */ - int (*cmp)(const void *key1, const void *key2); - /* key comparison function */ + u32 (*hash)(const void *key); /* hash func */ + int (*cmp)(const void *key1, const void *key2); /* comparison func */ }; struct hashtab_node { @@ -30,9 +30,9 @@ struct hashtab_node { }; struct hashtab { - struct hashtab_node **htable; /* hash table */ - u32 size; /* number of slots in hash table */ - u32 nel; /* number of elements in hash table */ + struct hashtab_node **htable; /* hash table */ + u32 size; /* number of slots in hash table */ + u32 nel; /* number of elements in hash table */ }; struct hashtab_info { @@ -48,8 +48,8 @@ struct hashtab_info { */ int hashtab_init(struct hashtab *h, u32 nel_hint); -int __hashtab_insert(struct hashtab *h, struct hashtab_node **dst, - void *key, void *datum); +int __hashtab_insert(struct hashtab *h, struct hashtab_node **dst, void *key, + void *datum); /* * Inserts the specified (key, datum) pair into the specified hash table. @@ -84,8 +84,8 @@ static inline int hashtab_insert(struct hashtab *h, void *key, void *datum, cur = cur->next; } - return __hashtab_insert(h, prev ? &prev->next : &h->htable[hvalue], - key, datum); + return __hashtab_insert(h, prev ? &prev->next : &h->htable[hvalue], key, + datum); } /* @@ -133,15 +133,13 @@ void hashtab_destroy(struct hashtab *h); * iterating through the hash table and will propagate the error * return to its caller. */ -int hashtab_map(struct hashtab *h, - int (*apply)(void *k, void *d, void *args), +int hashtab_map(struct hashtab *h, int (*apply)(void *k, void *d, void *args), void *args); int hashtab_duplicate(struct hashtab *new, struct hashtab *orig, - int (*copy)(struct hashtab_node *new, - struct hashtab_node *orig, void *args), - int (*destroy)(void *k, void *d, void *args), - void *args); + int (*copy)(struct hashtab_node *new, + struct hashtab_node *orig, void *args), + int (*destroy)(void *k, void *d, void *args), void *args); #ifdef CONFIG_SECURITY_SELINUX_DEBUG /* Fill info with some hash table statistics */ @@ -149,7 +147,8 @@ void hashtab_stat(struct hashtab *h, struct hashtab_info *info); #else static inline void hashtab_stat(struct hashtab *h, struct hashtab_info *info) { + return; } #endif -#endif /* _SS_HASHTAB_H */ +#endif /* _SS_HASHTAB_H */ -- cgit v1.2.3 From dfd9bb40a48ee7f54a89cde2a1094e886f955382 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 22 Feb 2024 18:52:29 -0500 Subject: selinux: fix style issues in security/selinux/ss/hashtab.c As part of on ongoing effort to perform more automated testing and provide more tools for individual developers to validate their patches before submitting, we are trying to make our code "clang-format clean". My hope is that once we have fixed all of our style "quirks", developers will be able to run clang-format on their patches to help avoid silly formatting problems and ensure their changes fit in well with the rest of the SELinux kernel code. Signed-off-by: Paul Moore --- security/selinux/ss/hashtab.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c index c05d8346a94a..754bedbde133 100644 --- a/security/selinux/ss/hashtab.c +++ b/security/selinux/ss/hashtab.c @@ -4,6 +4,7 @@ * * Author : Stephen Smalley, */ + #include #include #include @@ -47,8 +48,8 @@ int hashtab_init(struct hashtab *h, u32 nel_hint) return 0; } -int __hashtab_insert(struct hashtab *h, struct hashtab_node **dst, - void *key, void *datum) +int __hashtab_insert(struct hashtab *h, struct hashtab_node **dst, void *key, + void *datum) { struct hashtab_node *newnode; @@ -83,8 +84,7 @@ void hashtab_destroy(struct hashtab *h) h->htable = NULL; } -int hashtab_map(struct hashtab *h, - int (*apply)(void *k, void *d, void *args), +int hashtab_map(struct hashtab *h, int (*apply)(void *k, void *d, void *args), void *args) { u32 i; @@ -137,10 +137,9 @@ void hashtab_stat(struct hashtab *h, struct hashtab_info *info) #endif /* CONFIG_SECURITY_SELINUX_DEBUG */ int hashtab_duplicate(struct hashtab *new, struct hashtab *orig, - int (*copy)(struct hashtab_node *new, - struct hashtab_node *orig, void *args), - int (*destroy)(void *k, void *d, void *args), - void *args) + int (*copy)(struct hashtab_node *new, + struct hashtab_node *orig, void *args), + int (*destroy)(void *k, void *d, void *args), void *args) { struct hashtab_node *cur, *tmp, *tail; u32 i; @@ -178,7 +177,7 @@ int hashtab_duplicate(struct hashtab *new, struct hashtab *orig, return 0; - error: +error: for (i = 0; i < new->size; i++) { for (cur = new->htable[i]; cur; cur = tmp) { tmp = cur->next; @@ -193,7 +192,7 @@ int hashtab_duplicate(struct hashtab *new, struct hashtab *orig, void __init hashtab_cache_init(void) { - hashtab_node_cachep = kmem_cache_create("hashtab_node", - sizeof(struct hashtab_node), - 0, SLAB_PANIC, NULL); + hashtab_node_cachep = kmem_cache_create("hashtab_node", + sizeof(struct hashtab_node), 0, + SLAB_PANIC, NULL); } -- cgit v1.2.3 From 470948bc2dc9ae47f69b2ec0f1974e37f14af7b0 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 22 Feb 2024 18:52:30 -0500 Subject: selinux: fix style issues in security/selinux/ss/mls.h As part of on ongoing effort to perform more automated testing and provide more tools for individual developers to validate their patches before submitting, we are trying to make our code "clang-format clean". My hope is that once we have fixed all of our style "quirks", developers will be able to run clang-format on their patches to help avoid silly formatting problems and ensure their changes fit in well with the rest of the SELinux kernel code. Signed-off-by: Paul Moore --- security/selinux/ss/mls.h | 58 ++++++++++++++++------------------------------- 1 file changed, 19 insertions(+), 39 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h index 107681dd1824..07980636751f 100644 --- a/security/selinux/ss/mls.h +++ b/security/selinux/ss/mls.h @@ -4,19 +4,15 @@ * * Author : Stephen Smalley, */ + /* * Updated: Trusted Computer Solutions, Inc. + * Support for enhanced MLS infrastructure. + * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. * - * Support for enhanced MLS infrastructure. - * - * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. - */ -/* * Updated: Hewlett-Packard - * - * Added support to import/export the MLS label from NetLabel - * - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 + * Added support to import/export the MLS label from NetLabel + * Copyright (X) Hewlett-Packard Development Company, L.P., 2006 */ #ifndef _SS_MLS_H_ @@ -35,47 +31,32 @@ int mls_context_isvalid(struct policydb *p, struct context *c); int mls_range_isvalid(struct policydb *p, struct mls_range *r); int mls_level_isvalid(struct policydb *p, struct mls_level *l); -int mls_context_to_sid(struct policydb *p, - char oldc, - char *scontext, - struct context *context, - struct sidtab *s, - u32 def_sid); +int mls_context_to_sid(struct policydb *p, char oldc, char *scontext, + struct context *context, struct sidtab *s, u32 def_sid); int mls_from_string(struct policydb *p, char *str, struct context *context, gfp_t gfp_mask); int mls_range_set(struct context *context, struct mls_range *range); -int mls_convert_context(struct policydb *oldp, - struct policydb *newp, - struct context *oldc, - struct context *newc); +int mls_convert_context(struct policydb *oldp, struct policydb *newp, + struct context *oldc, struct context *newc); -int mls_compute_sid(struct policydb *p, - struct context *scontext, - struct context *tcontext, - u16 tclass, - u32 specified, - struct context *newcontext, - bool sock); +int mls_compute_sid(struct policydb *p, struct context *scontext, + struct context *tcontext, u16 tclass, u32 specified, + struct context *newcontext, bool sock); -int mls_setup_user_range(struct policydb *p, - struct context *fromcon, struct user_datum *user, - struct context *usercon); +int mls_setup_user_range(struct policydb *p, struct context *fromcon, + struct user_datum *user, struct context *usercon); #ifdef CONFIG_NETLABEL -void mls_export_netlbl_lvl(struct policydb *p, - struct context *context, +void mls_export_netlbl_lvl(struct policydb *p, struct context *context, struct netlbl_lsm_secattr *secattr); -void mls_import_netlbl_lvl(struct policydb *p, - struct context *context, +void mls_import_netlbl_lvl(struct policydb *p, struct context *context, struct netlbl_lsm_secattr *secattr); -int mls_export_netlbl_cat(struct policydb *p, - struct context *context, +int mls_export_netlbl_cat(struct policydb *p, struct context *context, struct netlbl_lsm_secattr *secattr); -int mls_import_netlbl_cat(struct policydb *p, - struct context *context, +int mls_import_netlbl_cat(struct policydb *p, struct context *context, struct netlbl_lsm_secattr *secattr); #else static inline void mls_export_netlbl_lvl(struct policydb *p, @@ -112,5 +93,4 @@ static inline u32 mls_range_hash(const struct mls_range *r, u32 hash) return hash; } -#endif /* _SS_MLS_H */ - +#endif /* _SS_MLS_H */ -- cgit v1.2.3 From 4afec3607b1487ecb556f890abd4d2c5c3bcfedd Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 22 Feb 2024 18:52:31 -0500 Subject: selinux: fix style issues in security/selinux/ss/mls.c As part of on ongoing effort to perform more automated testing and provide more tools for individual developers to validate their patches before submitting, we are trying to make our code "clang-format clean". My hope is that once we have fixed all of our style "quirks", developers will be able to run clang-format on their patches to help avoid silly formatting problems and ensure their changes fit in well with the rest of the SELinux kernel code. Signed-off-by: Paul Moore --- security/selinux/ss/mls.c | 83 +++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 50 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index cd38f5913b63..989c809d310d 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -4,19 +4,15 @@ * * Author : Stephen Smalley, */ + /* * Updated: Trusted Computer Solutions, Inc. + * Support for enhanced MLS infrastructure. + * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. * - * Support for enhanced MLS infrastructure. - * - * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. - */ -/* * Updated: Hewlett-Packard - * - * Added support to import/export the MLS label from NetLabel - * - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 + * Added support to import/export the MLS label from NetLabel + * Copyright (C) Hewlett-Packard Development Company, L.P., 2006 */ #include @@ -52,7 +48,8 @@ int mls_compute_context_len(struct policydb *p, struct context *context) head = -2; prev = -2; e = &context->range.level[l].cat; - ebitmap_for_each_positive_bit(e, node, i) { + ebitmap_for_each_positive_bit(e, node, i) + { if (i - prev > 1) { /* one or more negative bits are skipped */ if (head != prev) { @@ -86,8 +83,7 @@ int mls_compute_context_len(struct policydb *p, struct context *context) * the MLS fields of `context' into the string `*scontext'. * Update `*scontext' to point to the end of the MLS fields. */ -void mls_sid_to_context(struct policydb *p, - struct context *context, +void mls_sid_to_context(struct policydb *p, struct context *context, char **scontext) { char *scontextp, *nm; @@ -112,7 +108,8 @@ void mls_sid_to_context(struct policydb *p, head = -2; prev = -2; e = &context->range.level[l].cat; - ebitmap_for_each_positive_bit(e, node, i) { + ebitmap_for_each_positive_bit(e, node, i) + { if (i - prev > 1) { /* one or more negative bits are skipped */ if (prev != head) { @@ -230,12 +227,8 @@ int mls_context_isvalid(struct policydb *p, struct context *c) * Policy read-lock must be held for sidtab lookup. * */ -int mls_context_to_sid(struct policydb *pol, - char oldc, - char *scontext, - struct context *context, - struct sidtab *s, - u32 def_sid) +int mls_context_to_sid(struct policydb *pol, char oldc, char *scontext, + struct context *context, struct sidtab *s, u32 def_sid) { char *sensitivity, *cur_cat, *next_cat, *rngptr; struct level_datum *levdatum; @@ -333,7 +326,8 @@ int mls_context_to_sid(struct policydb *pol, return -EINVAL; for (i = catdatum->value; i < rngdatum->value; i++) { - rc = ebitmap_set_bit(&context->range.level[l].cat, i, 1); + rc = ebitmap_set_bit( + &context->range.level[l].cat, i, 1); if (rc) return rc; } @@ -371,8 +365,8 @@ int mls_from_string(struct policydb *p, char *str, struct context *context, if (!tmpstr) { rc = -ENOMEM; } else { - rc = mls_context_to_sid(p, ':', tmpstr, context, - NULL, SECSID_NULL); + rc = mls_context_to_sid(p, ':', tmpstr, context, NULL, + SECSID_NULL); kfree(tmpstr); } @@ -382,8 +376,7 @@ int mls_from_string(struct policydb *p, char *str, struct context *context, /* * Copies the MLS range `range' into `context'. */ -int mls_range_set(struct context *context, - struct mls_range *range) +int mls_range_set(struct context *context, struct mls_range *range) { int l, rc = 0; @@ -399,9 +392,8 @@ int mls_range_set(struct context *context, return rc; } -int mls_setup_user_range(struct policydb *p, - struct context *fromcon, struct user_datum *user, - struct context *usercon) +int mls_setup_user_range(struct policydb *p, struct context *fromcon, + struct user_datum *user, struct context *usercon) { if (p->mls_enabled) { struct mls_level *fromcon_sen = &(fromcon->range.level[0]); @@ -444,10 +436,8 @@ int mls_setup_user_range(struct policydb *p, * policy `oldp' to the values specified in the policy `newp', * storing the resulting context in `newc'. */ -int mls_convert_context(struct policydb *oldp, - struct policydb *newp, - struct context *oldc, - struct context *newc) +int mls_convert_context(struct policydb *oldp, struct policydb *newp, + struct context *oldc, struct context *newc) { struct level_datum *levdatum; struct cat_datum *catdatum; @@ -468,8 +458,9 @@ int mls_convert_context(struct policydb *oldp, return -EINVAL; newc->range.level[l].sens = levdatum->level->sens; - ebitmap_for_each_positive_bit(&oldc->range.level[l].cat, - node, i) { + ebitmap_for_each_positive_bit(&oldc->range.level[l].cat, node, + i) + { int rc; catdatum = symtab_search(&newp->p_cats, @@ -486,13 +477,9 @@ int mls_convert_context(struct policydb *oldp, return 0; } -int mls_compute_sid(struct policydb *p, - struct context *scontext, - struct context *tcontext, - u16 tclass, - u32 specified, - struct context *newcontext, - bool sock) +int mls_compute_sid(struct policydb *p, struct context *scontext, + struct context *tcontext, u16 tclass, u32 specified, + struct context *newcontext, bool sock) { struct range_trans rtr; struct mls_range *r; @@ -532,8 +519,8 @@ int mls_compute_sid(struct policydb *p, case DEFAULT_TARGET_LOW_HIGH: return mls_context_cpy(newcontext, tcontext); case DEFAULT_GLBLUB: - return mls_context_glblub(newcontext, - scontext, tcontext); + return mls_context_glblub(newcontext, scontext, + tcontext); } fallthrough; @@ -563,8 +550,7 @@ int mls_compute_sid(struct policydb *p, * NetLabel MLS sensitivity level field. * */ -void mls_export_netlbl_lvl(struct policydb *p, - struct context *context, +void mls_export_netlbl_lvl(struct policydb *p, struct context *context, struct netlbl_lsm_secattr *secattr) { if (!p->mls_enabled) @@ -585,8 +571,7 @@ void mls_export_netlbl_lvl(struct policydb *p, * NetLabel MLS sensitivity level into the context. * */ -void mls_import_netlbl_lvl(struct policydb *p, - struct context *context, +void mls_import_netlbl_lvl(struct policydb *p, struct context *context, struct netlbl_lsm_secattr *secattr) { if (!p->mls_enabled) @@ -607,8 +592,7 @@ void mls_import_netlbl_lvl(struct policydb *p, * MLS category field. Returns zero on success, negative values on failure. * */ -int mls_export_netlbl_cat(struct policydb *p, - struct context *context, +int mls_export_netlbl_cat(struct policydb *p, struct context *context, struct netlbl_lsm_secattr *secattr) { int rc; @@ -637,8 +621,7 @@ int mls_export_netlbl_cat(struct policydb *p, * negative values on failure. * */ -int mls_import_netlbl_cat(struct policydb *p, - struct context *context, +int mls_import_netlbl_cat(struct policydb *p, struct context *context, struct netlbl_lsm_secattr *secattr) { int rc; -- cgit v1.2.3 From 793f9add024abfaa8dfeac48704e39ca8649f02a Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 22 Feb 2024 18:52:32 -0500 Subject: selinux: fix style issues in security/selinux/ss/mls_types.h As part of on ongoing effort to perform more automated testing and provide more tools for individual developers to validate their patches before submitting, we are trying to make our code "clang-format clean". My hope is that once we have fixed all of our style "quirks", developers will be able to run clang-format on their patches to help avoid silly formatting problems and ensure their changes fit in well with the rest of the SELinux kernel code. Signed-off-by: Paul Moore --- security/selinux/ss/mls_types.h | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/mls_types.h b/security/selinux/ss/mls_types.h index f492cf148891..7ef6e8cb0cf4 100644 --- a/security/selinux/ss/mls_types.h +++ b/security/selinux/ss/mls_types.h @@ -4,12 +4,11 @@ * * Author : Stephen Smalley, */ + /* * Updated: Trusted Computer Solutions, Inc. - * - * Support for enhanced MLS infrastructure. - * - * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. + * Support for enhanced MLS infrastructure. + * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. */ #ifndef _SS_MLS_TYPES_H_ @@ -19,34 +18,35 @@ #include "ebitmap.h" struct mls_level { - u32 sens; /* sensitivity */ - struct ebitmap cat; /* category set */ + u32 sens; /* sensitivity */ + struct ebitmap cat; /* category set */ }; struct mls_range { struct mls_level level[2]; /* low == level[0], high == level[1] */ }; -static inline int mls_level_eq(const struct mls_level *l1, const struct mls_level *l2) +static inline int mls_level_eq(const struct mls_level *l1, + const struct mls_level *l2) { - return ((l1->sens == l2->sens) && - ebitmap_cmp(&l1->cat, &l2->cat)); + return ((l1->sens == l2->sens) && ebitmap_cmp(&l1->cat, &l2->cat)); } -static inline int mls_level_dom(const struct mls_level *l1, const struct mls_level *l2) +static inline int mls_level_dom(const struct mls_level *l1, + const struct mls_level *l2) { return ((l1->sens >= l2->sens) && ebitmap_contains(&l1->cat, &l2->cat, 0)); } #define mls_level_incomp(l1, l2) \ -(!mls_level_dom((l1), (l2)) && !mls_level_dom((l2), (l1))) + (!mls_level_dom((l1), (l2)) && !mls_level_dom((l2), (l1))) #define mls_level_between(l1, l2, l3) \ -(mls_level_dom((l1), (l2)) && mls_level_dom((l3), (l1))) + (mls_level_dom((l1), (l2)) && mls_level_dom((l3), (l1))) -#define mls_range_contains(r1, r2) \ -(mls_level_dom(&(r2).level[0], &(r1).level[0]) && \ - mls_level_dom(&(r1).level[1], &(r2).level[1])) +#define mls_range_contains(r1, r2) \ + (mls_level_dom(&(r2).level[0], &(r1).level[0]) && \ + mls_level_dom(&(r1).level[1], &(r2).level[1])) -#endif /* _SS_MLS_TYPES_H_ */ +#endif /* _SS_MLS_TYPES_H_ */ -- cgit v1.2.3 From a32582db36dcf3b23f860e092485e5e06b1b966c Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 22 Feb 2024 18:52:33 -0500 Subject: selinux: fix style issues in security/selinux/ss/policydb.h As part of on ongoing effort to perform more automated testing and provide more tools for individual developers to validate their patches before submitting, we are trying to make our code "clang-format clean". My hope is that once we have fixed all of our style "quirks", developers will be able to run clang-format on their patches to help avoid silly formatting problems and ensure their changes fit in well with the rest of the SELinux kernel code. Signed-off-by: Paul Moore --- security/selinux/ss/policydb.h | 192 ++++++++++++++++++++--------------------- 1 file changed, 95 insertions(+), 97 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index b97cda489753..4bba386264a3 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h @@ -8,15 +8,13 @@ /* * Updated: Trusted Computer Solutions, Inc. + * Support for enhanced MLS infrastructure. + * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * - * Support for enhanced MLS infrastructure. - * - * Updated: Frank Mayer and Karl MacMillan - * - * Added conditional policy language extensions - * - * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. - * Copyright (C) 2003 - 2004 Tresys Technology, LLC + * Updated: Frank Mayer and + * Karl MacMillan + * Added conditional policy language extensions + * Copyright (C) 2003-2004 Tresys Technology, LLC */ #ifndef _SS_POLICYDB_H_ @@ -39,104 +37,103 @@ /* Permission attributes */ struct perm_datum { - u32 value; /* permission bit + 1 */ + u32 value; /* permission bit + 1 */ }; /* Attributes of a common prefix for access vectors */ struct common_datum { - u32 value; /* internal common value */ - struct symtab permissions; /* common permissions */ + u32 value; /* internal common value */ + struct symtab permissions; /* common permissions */ }; /* Class attributes */ struct class_datum { - u32 value; /* class value */ - char *comkey; /* common name */ - struct common_datum *comdatum; /* common datum */ - struct symtab permissions; /* class-specific permission symbol table */ - struct constraint_node *constraints; /* constraints on class permissions */ - struct constraint_node *validatetrans; /* special transition rules */ + u32 value; /* class value */ + char *comkey; /* common name */ + struct common_datum *comdatum; /* common datum */ + struct symtab permissions; /* class-specific permission symbol table */ + struct constraint_node *constraints; /* constraints on class perms */ + struct constraint_node *validatetrans; /* special transition rules */ /* Options how a new object user, role, and type should be decided */ -#define DEFAULT_SOURCE 1 -#define DEFAULT_TARGET 2 +#define DEFAULT_SOURCE 1 +#define DEFAULT_TARGET 2 char default_user; char default_role; char default_type; /* Options how a new object range should be decided */ -#define DEFAULT_SOURCE_LOW 1 -#define DEFAULT_SOURCE_HIGH 2 -#define DEFAULT_SOURCE_LOW_HIGH 3 -#define DEFAULT_TARGET_LOW 4 -#define DEFAULT_TARGET_HIGH 5 -#define DEFAULT_TARGET_LOW_HIGH 6 +#define DEFAULT_SOURCE_LOW 1 +#define DEFAULT_SOURCE_HIGH 2 +#define DEFAULT_SOURCE_LOW_HIGH 3 +#define DEFAULT_TARGET_LOW 4 +#define DEFAULT_TARGET_HIGH 5 +#define DEFAULT_TARGET_LOW_HIGH 6 #define DEFAULT_GLBLUB 7 char default_range; }; /* Role attributes */ struct role_datum { - u32 value; /* internal role value */ - u32 bounds; /* boundary of role */ - struct ebitmap dominates; /* set of roles dominated by this role */ - struct ebitmap types; /* set of authorized types for role */ + u32 value; /* internal role value */ + u32 bounds; /* boundary of role */ + struct ebitmap dominates; /* set of roles dominated by this role */ + struct ebitmap types; /* set of authorized types for role */ }; struct role_trans_key { - u32 role; /* current role */ - u32 type; /* program executable type, or new object type */ - u32 tclass; /* process class, or new object class */ + u32 role; /* current role */ + u32 type; /* program executable type, or new object type */ + u32 tclass; /* process class, or new object class */ }; struct role_trans_datum { - u32 new_role; /* new role */ + u32 new_role; /* new role */ }; struct filename_trans_key { - u32 ttype; /* parent dir context */ - u16 tclass; /* class of new object */ - const char *name; /* last path component */ + u32 ttype; /* parent dir context */ + u16 tclass; /* class of new object */ + const char *name; /* last path component */ }; struct filename_trans_datum { - struct ebitmap stypes; /* bitmap of source types for this otype */ - u32 otype; /* resulting type of new object */ - struct filename_trans_datum *next; /* record for next otype*/ + struct ebitmap stypes; /* bitmap of source types for this otype */ + u32 otype; /* resulting type of new object */ + struct filename_trans_datum *next; /* record for next otype*/ }; struct role_allow { - u32 role; /* current role */ - u32 new_role; /* new role */ + u32 role; /* current role */ + u32 new_role; /* new role */ struct role_allow *next; }; /* Type attributes */ struct type_datum { - u32 value; /* internal type value */ - u32 bounds; /* boundary of type */ - unsigned char primary; /* primary name? */ - unsigned char attribute;/* attribute ?*/ + u32 value; /* internal type value */ + u32 bounds; /* boundary of type */ + unsigned char primary; /* primary name? */ + unsigned char attribute; /* attribute ?*/ }; /* User attributes */ struct user_datum { - u32 value; /* internal user value */ - u32 bounds; /* bounds of user */ - struct ebitmap roles; /* set of authorized roles for user */ - struct mls_range range; /* MLS range (min - max) for user */ - struct mls_level dfltlevel; /* default login MLS level for user */ + u32 value; /* internal user value */ + u32 bounds; /* bounds of user */ + struct ebitmap roles; /* set of authorized roles for user */ + struct mls_range range; /* MLS range (min - max) for user */ + struct mls_level dfltlevel; /* default login MLS level for user */ }; - /* Sensitivity attributes */ struct level_datum { - struct mls_level *level; /* sensitivity and associated categories */ - unsigned char isalias; /* is this sensitivity an alias for another? */ + struct mls_level *level; /* sensitivity and associated categories */ + unsigned char isalias; /* is this sensitivity an alias for another? */ }; /* Category attributes */ struct cat_datum { - u32 value; /* internal category bit + 1 */ - unsigned char isalias; /* is this category an alias for another? */ + u32 value; /* internal category bit + 1 */ + unsigned char isalias; /* is this category an alias for another? */ }; struct range_trans { @@ -147,7 +144,7 @@ struct range_trans { /* Boolean data type */ struct cond_bool_datum { - __u32 value; /* internal type value */ + __u32 value; /* internal type value */ int state; }; @@ -173,20 +170,20 @@ struct type_set { */ struct ocontext { union { - char *name; /* name of initial SID, fs, netif, fstype, path */ + char *name; /* name of initial SID, fs, netif, fstype, path */ struct { u8 protocol; u16 low_port; u16 high_port; - } port; /* TCP or UDP port information */ + } port; /* TCP or UDP port information */ struct { u32 addr; u32 mask; - } node; /* node information */ + } node; /* node information */ struct { u32 addr[4]; u32 mask[4]; - } node6; /* IPv6 node information */ + } node6; /* IPv6 node information */ struct { u64 subnet_prefix; u16 low_pkey; @@ -198,11 +195,11 @@ struct ocontext { } ibendport; } u; union { - u32 sclass; /* security class for genfs */ - u32 behavior; /* labeling behavior for fs_use */ + u32 sclass; /* security class for genfs */ + u32 behavior; /* labeling behavior for fs_use */ } v; - struct context context[2]; /* security context(s) */ - u32 sid[2]; /* SID(s) */ + struct context context[2]; /* security context(s) */ + u32 sid[2]; /* SID(s) */ struct ocontext *next; }; @@ -221,19 +218,19 @@ struct genfs { #define SYM_BOOLS 5 #define SYM_LEVELS 6 #define SYM_CATS 7 -#define SYM_NUM 8 +#define SYM_NUM 8 /* object context array indices */ -#define OCON_ISID 0 /* initial SIDs */ -#define OCON_FS 1 /* unlabeled file systems (deprecated) */ -#define OCON_PORT 2 /* TCP and UDP port numbers */ -#define OCON_NETIF 3 /* network interfaces */ -#define OCON_NODE 4 /* nodes */ -#define OCON_FSUSE 5 /* fs_use */ -#define OCON_NODE6 6 /* IPv6 nodes */ -#define OCON_IBPKEY 7 /* Infiniband PKeys */ -#define OCON_IBENDPORT 8 /* Infiniband end ports */ -#define OCON_NUM 9 +#define OCON_ISID 0 /* initial SIDs */ +#define OCON_FS 1 /* unlabeled file systems (deprecated) */ +#define OCON_PORT 2 /* TCP and UDP port numbers */ +#define OCON_NETIF 3 /* network interfaces */ +#define OCON_NODE 4 /* nodes */ +#define OCON_FSUSE 5 /* fs_use */ +#define OCON_NODE6 6 /* IPv6 nodes */ +#define OCON_IBPKEY 7 /* Infiniband PKeys */ +#define OCON_IBENDPORT 8 /* Infiniband end ports */ +#define OCON_NUM 9 /* The policy database */ struct policydb { @@ -243,15 +240,15 @@ struct policydb { struct symtab symtab[SYM_NUM]; #define p_commons symtab[SYM_COMMONS] #define p_classes symtab[SYM_CLASSES] -#define p_roles symtab[SYM_ROLES] -#define p_types symtab[SYM_TYPES] -#define p_users symtab[SYM_USERS] -#define p_bools symtab[SYM_BOOLS] -#define p_levels symtab[SYM_LEVELS] -#define p_cats symtab[SYM_CATS] +#define p_roles symtab[SYM_ROLES] +#define p_types symtab[SYM_TYPES] +#define p_users symtab[SYM_USERS] +#define p_bools symtab[SYM_BOOLS] +#define p_levels symtab[SYM_LEVELS] +#define p_cats symtab[SYM_CATS] /* symbol names indexed by (value - 1) */ - char **sym_val_to_name[SYM_NUM]; + char **sym_val_to_name[SYM_NUM]; /* class, role, and user attributes indexed by (value - 1) */ struct class_datum **class_val_to_struct; @@ -324,25 +321,25 @@ extern int policydb_role_isvalid(struct policydb *p, unsigned int role); extern int policydb_read(struct policydb *p, void *fp); extern int policydb_write(struct policydb *p, void *fp); -extern struct filename_trans_datum *policydb_filenametr_search( - struct policydb *p, struct filename_trans_key *key); +extern struct filename_trans_datum * +policydb_filenametr_search(struct policydb *p, struct filename_trans_key *key); -extern struct mls_range *policydb_rangetr_search( - struct policydb *p, struct range_trans *key); +extern struct mls_range *policydb_rangetr_search(struct policydb *p, + struct range_trans *key); -extern struct role_trans_datum *policydb_roletr_search( - struct policydb *p, struct role_trans_key *key); +extern struct role_trans_datum * +policydb_roletr_search(struct policydb *p, struct role_trans_key *key); -#define POLICYDB_CONFIG_MLS 1 +#define POLICYDB_CONFIG_MLS 1 /* the config flags related to unknown classes/perms are bits 2 and 3 */ -#define REJECT_UNKNOWN 0x00000002 -#define ALLOW_UNKNOWN 0x00000004 +#define REJECT_UNKNOWN 0x00000002 +#define ALLOW_UNKNOWN 0x00000004 -#define OBJECT_R "object_r" +#define OBJECT_R "object_r" #define OBJECT_R_VAL 1 -#define POLICYDB_MAGIC SELINUX_MAGIC +#define POLICYDB_MAGIC SELINUX_MAGIC #define POLICYDB_STRING "SE Linux" struct policy_file { @@ -366,7 +363,8 @@ static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes) return 0; } -static inline int put_entry(const void *buf, size_t bytes, size_t num, struct policy_file *fp) +static inline int put_entry(const void *buf, size_t bytes, size_t num, + struct policy_file *fp) { size_t len; @@ -382,7 +380,8 @@ static inline int put_entry(const void *buf, size_t bytes, size_t num, struct po return 0; } -static inline char *sym_name(struct policydb *p, unsigned int sym_num, unsigned int element_nr) +static inline char *sym_name(struct policydb *p, unsigned int sym_num, + unsigned int element_nr) { return p->sym_val_to_name[sym_num][element_nr]; } @@ -390,5 +389,4 @@ static inline char *sym_name(struct policydb *p, unsigned int sym_num, unsigned extern u16 string_to_security_class(struct policydb *p, const char *name); extern u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name); -#endif /* _SS_POLICYDB_H_ */ - +#endif /* _SS_POLICYDB_H_ */ -- cgit v1.2.3 From ec12c6ee2ae643693902013f50cade6764eae75c Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 22 Feb 2024 18:52:34 -0500 Subject: selinux: fix style issues in security/selinux/ss/policydb.c As part of on ongoing effort to perform more automated testing and provide more tools for individual developers to validate their patches before submitting, we are trying to make our code "clang-format clean". My hope is that once we have fixed all of our style "quirks", developers will be able to run clang-format on their patches to help avoid silly formatting problems and ensure their changes fit in well with the rest of the SELinux kernel code. Signed-off-by: Paul Moore --- security/selinux/ss/policydb.c | 405 ++++++++++++++++++++++------------------- 1 file changed, 213 insertions(+), 192 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 3b19ad28c922..3d22d5baa829 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -7,25 +7,21 @@ /* * Updated: Trusted Computer Solutions, Inc. + * Support for enhanced MLS infrastructure. + * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * - * Support for enhanced MLS infrastructure. - * - * Updated: Frank Mayer and Karl MacMillan - * - * Added conditional policy language extensions + * Updated: Frank Mayer and + * Karl MacMillan + * Added conditional policy language extensions + * Copyright (C) 2003-2004 Tresys Technology, LLC * * Updated: Hewlett-Packard - * - * Added support for the policy capability bitmap + * Added support for the policy capability bitmap + * Copyright (C) 2007 Hewlett-Packard Development Company, L.P. * * Update: Mellanox Techonologies - * - * Added Infiniband support - * - * Copyright (C) 2016 Mellanox Techonologies - * Copyright (C) 2007 Hewlett-Packard Development Company, L.P. - * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. - * Copyright (C) 2003 - 2004 Tresys Technology, LLC + * Added Infiniband support + * Copyright (C) 2016 Mellanox Techonologies */ #include @@ -42,6 +38,7 @@ #include "services.h" #ifdef CONFIG_SECURITY_SELINUX_DEBUG +/* clang-format off */ static const char *const symtab_name[SYM_NUM] = { "common prefixes", "classes", @@ -52,6 +49,7 @@ static const char *const symtab_name[SYM_NUM] = { "levels", "categories", }; +/* clang-format off */ #endif struct policydb_compat_info { @@ -63,103 +61,104 @@ struct policydb_compat_info { /* These need to be updated if SYM_NUM or OCON_NUM changes */ static const struct policydb_compat_info policydb_compat[] = { { - .version = POLICYDB_VERSION_BASE, - .sym_num = SYM_NUM - 3, - .ocon_num = OCON_NUM - 3, + .version = POLICYDB_VERSION_BASE, + .sym_num = SYM_NUM - 3, + .ocon_num = OCON_NUM - 3, }, { - .version = POLICYDB_VERSION_BOOL, - .sym_num = SYM_NUM - 2, - .ocon_num = OCON_NUM - 3, + .version = POLICYDB_VERSION_BOOL, + .sym_num = SYM_NUM - 2, + .ocon_num = OCON_NUM - 3, }, { - .version = POLICYDB_VERSION_IPV6, - .sym_num = SYM_NUM - 2, - .ocon_num = OCON_NUM - 2, + .version = POLICYDB_VERSION_IPV6, + .sym_num = SYM_NUM - 2, + .ocon_num = OCON_NUM - 2, }, { - .version = POLICYDB_VERSION_NLCLASS, - .sym_num = SYM_NUM - 2, - .ocon_num = OCON_NUM - 2, + .version = POLICYDB_VERSION_NLCLASS, + .sym_num = SYM_NUM - 2, + .ocon_num = OCON_NUM - 2, }, { - .version = POLICYDB_VERSION_MLS, - .sym_num = SYM_NUM, - .ocon_num = OCON_NUM - 2, + .version = POLICYDB_VERSION_MLS, + .sym_num = SYM_NUM, + .ocon_num = OCON_NUM - 2, }, { - .version = POLICYDB_VERSION_AVTAB, - .sym_num = SYM_NUM, - .ocon_num = OCON_NUM - 2, + .version = POLICYDB_VERSION_AVTAB, + .sym_num = SYM_NUM, + .ocon_num = OCON_NUM - 2, }, { - .version = POLICYDB_VERSION_RANGETRANS, - .sym_num = SYM_NUM, - .ocon_num = OCON_NUM - 2, + .version = POLICYDB_VERSION_RANGETRANS, + .sym_num = SYM_NUM, + .ocon_num = OCON_NUM - 2, }, { - .version = POLICYDB_VERSION_POLCAP, - .sym_num = SYM_NUM, - .ocon_num = OCON_NUM - 2, + .version = POLICYDB_VERSION_POLCAP, + .sym_num = SYM_NUM, + .ocon_num = OCON_NUM - 2, }, { - .version = POLICYDB_VERSION_PERMISSIVE, - .sym_num = SYM_NUM, - .ocon_num = OCON_NUM - 2, + .version = POLICYDB_VERSION_PERMISSIVE, + .sym_num = SYM_NUM, + .ocon_num = OCON_NUM - 2, }, { - .version = POLICYDB_VERSION_BOUNDARY, - .sym_num = SYM_NUM, - .ocon_num = OCON_NUM - 2, + .version = POLICYDB_VERSION_BOUNDARY, + .sym_num = SYM_NUM, + .ocon_num = OCON_NUM - 2, }, { - .version = POLICYDB_VERSION_FILENAME_TRANS, - .sym_num = SYM_NUM, - .ocon_num = OCON_NUM - 2, + .version = POLICYDB_VERSION_FILENAME_TRANS, + .sym_num = SYM_NUM, + .ocon_num = OCON_NUM - 2, }, { - .version = POLICYDB_VERSION_ROLETRANS, - .sym_num = SYM_NUM, - .ocon_num = OCON_NUM - 2, + .version = POLICYDB_VERSION_ROLETRANS, + .sym_num = SYM_NUM, + .ocon_num = OCON_NUM - 2, }, { - .version = POLICYDB_VERSION_NEW_OBJECT_DEFAULTS, - .sym_num = SYM_NUM, - .ocon_num = OCON_NUM - 2, + .version = POLICYDB_VERSION_NEW_OBJECT_DEFAULTS, + .sym_num = SYM_NUM, + .ocon_num = OCON_NUM - 2, }, { - .version = POLICYDB_VERSION_DEFAULT_TYPE, - .sym_num = SYM_NUM, - .ocon_num = OCON_NUM - 2, + .version = POLICYDB_VERSION_DEFAULT_TYPE, + .sym_num = SYM_NUM, + .ocon_num = OCON_NUM - 2, }, { - .version = POLICYDB_VERSION_CONSTRAINT_NAMES, - .sym_num = SYM_NUM, - .ocon_num = OCON_NUM - 2, + .version = POLICYDB_VERSION_CONSTRAINT_NAMES, + .sym_num = SYM_NUM, + .ocon_num = OCON_NUM - 2, }, { - .version = POLICYDB_VERSION_XPERMS_IOCTL, - .sym_num = SYM_NUM, - .ocon_num = OCON_NUM - 2, + .version = POLICYDB_VERSION_XPERMS_IOCTL, + .sym_num = SYM_NUM, + .ocon_num = OCON_NUM - 2, }, { - .version = POLICYDB_VERSION_INFINIBAND, - .sym_num = SYM_NUM, - .ocon_num = OCON_NUM, + .version = POLICYDB_VERSION_INFINIBAND, + .sym_num = SYM_NUM, + .ocon_num = OCON_NUM, }, { - .version = POLICYDB_VERSION_GLBLUB, - .sym_num = SYM_NUM, - .ocon_num = OCON_NUM, + .version = POLICYDB_VERSION_GLBLUB, + .sym_num = SYM_NUM, + .ocon_num = OCON_NUM, }, { - .version = POLICYDB_VERSION_COMP_FTRANS, - .sym_num = SYM_NUM, - .ocon_num = OCON_NUM, + .version = POLICYDB_VERSION_COMP_FTRANS, + .sym_num = SYM_NUM, + .ocon_num = OCON_NUM, }, }; -static const struct policydb_compat_info *policydb_lookup_compat(unsigned int version) +static const struct policydb_compat_info * +policydb_lookup_compat(unsigned int version) { unsigned int i; @@ -312,7 +311,8 @@ static int cat_destroy(void *key, void *datum, void *p) return 0; } -static int (*const destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) = { +/* clang-format off */ +static int (*const destroy_f[SYM_NUM])(void *key, void *datum, void *datap) = { common_destroy, cls_destroy, role_destroy, @@ -322,6 +322,7 @@ static int (*const destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) = { sens_destroy, cat_destroy, }; +/* clang-format on */ static int filenametr_destroy(void *key, void *datum, void *p) { @@ -366,8 +367,8 @@ static void ocontext_destroy(struct ocontext *c, unsigned int i) context_destroy(&c->context[0]); context_destroy(&c->context[1]); - if (i == OCON_ISID || i == OCON_FS || - i == OCON_NETIF || i == OCON_FSUSE) + if (i == OCON_ISID || i == OCON_FS || i == OCON_NETIF || + i == OCON_FSUSE) kfree(c->u.name); kfree(c); } @@ -429,7 +430,6 @@ static int filenametr_cmp(const void *k1, const void *k2) return v; return strcmp(ft1->name, ft2->name); - } static const struct hashtab_key_params filenametr_key_params = { @@ -437,8 +437,8 @@ static const struct hashtab_key_params filenametr_key_params = { .cmp = filenametr_cmp, }; -struct filename_trans_datum *policydb_filenametr_search( - struct policydb *p, struct filename_trans_key *key) +struct filename_trans_datum * +policydb_filenametr_search(struct policydb *p, struct filename_trans_key *key) { return hashtab_search(&p->filename_trans, key, filenametr_key_params); } @@ -448,7 +448,7 @@ static u32 rangetr_hash(const void *k) const struct range_trans *key = k; return key->source_type + (key->target_type << 3) + - (key->target_class << 5); + (key->target_class << 5); } static int rangetr_cmp(const void *k1, const void *k2) @@ -484,7 +484,8 @@ static u32 role_trans_hash(const void *k) { const struct role_trans_key *key = k; - return jhash_3words(key->role, key->type, (u32)key->tclass << 16 | key->tclass, 0); + return jhash_3words(key->role, key->type, + (u32)key->tclass << 16 | key->tclass, 0); } static int role_trans_cmp(const void *k1, const void *k2) @@ -576,9 +577,8 @@ static int role_index(void *key, void *datum, void *datap) role = datum; p = datap; - if (!role->value - || role->value > p->p_roles.nprim - || role->bounds > p->p_roles.nprim) + if (!role->value || role->value > p->p_roles.nprim || + role->bounds > p->p_roles.nprim) return -EINVAL; p->sym_val_to_name[SYM_ROLES][role->value - 1] = key; @@ -595,9 +595,8 @@ static int type_index(void *key, void *datum, void *datap) p = datap; if (typdatum->primary) { - if (!typdatum->value - || typdatum->value > p->p_types.nprim - || typdatum->bounds > p->p_types.nprim) + if (!typdatum->value || typdatum->value > p->p_types.nprim || + typdatum->bounds > p->p_types.nprim) return -EINVAL; p->sym_val_to_name[SYM_TYPES][typdatum->value - 1] = key; p->type_val_to_struct[typdatum->value - 1] = typdatum; @@ -613,9 +612,8 @@ static int user_index(void *key, void *datum, void *datap) usrdatum = datum; p = datap; - if (!usrdatum->value - || usrdatum->value > p->p_users.nprim - || usrdatum->bounds > p->p_users.nprim) + if (!usrdatum->value || usrdatum->value > p->p_users.nprim || + usrdatum->bounds > p->p_users.nprim) return -EINVAL; p->sym_val_to_name[SYM_USERS][usrdatum->value - 1] = key; @@ -660,7 +658,8 @@ static int cat_index(void *key, void *datum, void *datap) return 0; } -static int (*const index_f[SYM_NUM]) (void *key, void *datum, void *datap) = { +/* clang-format off */ +static int (*const index_f[SYM_NUM])(void *key, void *datum, void *datap) = { common_index, class_index, role_index, @@ -670,6 +669,7 @@ static int (*const index_f[SYM_NUM]) (void *key, void *datum, void *datap) = { sens_index, cat_index, }; +/* clang-format on */ #ifdef CONFIG_SECURITY_SELINUX_DEBUG static void hash_eval(struct hashtab *h, const char *hash_name) @@ -677,9 +677,10 @@ static void hash_eval(struct hashtab *h, const char *hash_name) struct hashtab_info info; hashtab_stat(h, &info); - pr_debug("SELinux: %s: %d entries and %d/%d buckets used, longest chain length %d, sum of chain length^2 %llu\n", - hash_name, h->nel, info.slots_used, h->size, - info.max_chain_len, info.chain2_len_sum); + pr_debug( + "SELinux: %s: %d entries and %d/%d buckets used, longest chain length %d, sum of chain length^2 %llu\n", + hash_name, h->nel, info.slots_used, h->size, info.max_chain_len, + info.chain2_len_sum); } static void symtab_hash_eval(struct symtab *s) @@ -710,16 +711,17 @@ static int policydb_index(struct policydb *p) int i, rc; if (p->mls_enabled) - pr_debug("SELinux: %d users, %d roles, %d types, %d bools, %d sens, %d cats\n", - p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, - p->p_bools.nprim, p->p_levels.nprim, p->p_cats.nprim); + pr_debug( + "SELinux: %d users, %d roles, %d types, %d bools, %d sens, %d cats\n", + p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, + p->p_bools.nprim, p->p_levels.nprim, p->p_cats.nprim); else pr_debug("SELinux: %d users, %d roles, %d types, %d bools\n", p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim); - pr_debug("SELinux: %d classes, %d rules\n", - p->p_classes.nprim, p->te_avtab.nel); + pr_debug("SELinux: %d classes, %d rules\n", p->p_classes.nprim, + p->te_avtab.nel); avtab_hash_eval(&p->te_avtab, "rules"); symtab_hash_eval(p->symtab); @@ -730,21 +732,18 @@ static int policydb_index(struct policydb *p) if (!p->class_val_to_struct) return -ENOMEM; - p->role_val_to_struct = kcalloc(p->p_roles.nprim, - sizeof(*p->role_val_to_struct), - GFP_KERNEL); + p->role_val_to_struct = kcalloc( + p->p_roles.nprim, sizeof(*p->role_val_to_struct), GFP_KERNEL); if (!p->role_val_to_struct) return -ENOMEM; - p->user_val_to_struct = kcalloc(p->p_users.nprim, - sizeof(*p->user_val_to_struct), - GFP_KERNEL); + p->user_val_to_struct = kcalloc( + p->p_users.nprim, sizeof(*p->user_val_to_struct), GFP_KERNEL); if (!p->user_val_to_struct) return -ENOMEM; - p->type_val_to_struct = kvcalloc(p->p_types.nprim, - sizeof(*p->type_val_to_struct), - GFP_KERNEL); + p->type_val_to_struct = kvcalloc( + p->p_types.nprim, sizeof(*p->type_val_to_struct), GFP_KERNEL); if (!p->type_val_to_struct) return -ENOMEM; @@ -754,8 +753,7 @@ static int policydb_index(struct policydb *p) for (i = 0; i < SYM_NUM; i++) { p->sym_val_to_name[i] = kvcalloc(p->symtab[i].nprim, - sizeof(char *), - GFP_KERNEL); + sizeof(char *), GFP_KERNEL); if (!p->sym_val_to_name[i]) return -ENOMEM; @@ -857,8 +855,7 @@ void policydb_destroy(struct policydb *p) int policydb_load_isids(struct policydb *p, struct sidtab *s) { struct ocontext *head, *c; - bool isid_init_supported = ebitmap_get_bit(&p->policycaps, - POLICYDB_CAP_USERSPACE_INITIAL_CONTEXT); + bool isid_init; int rc; rc = sidtab_init(s); @@ -867,6 +864,9 @@ int policydb_load_isids(struct policydb *p, struct sidtab *s) return rc; } + isid_init = ebitmap_get_bit(&p->policycaps, + POLICYDB_CAP_USERSPACE_INITIAL_CONTEXT); + head = p->ocontexts[OCON_ISID]; for (c = head; c; c = c->next) { u32 sid = c->sid[0]; @@ -886,7 +886,7 @@ int policydb_load_isids(struct policydb *p, struct sidtab *s) * Also ignore SECINITSID_INIT if the policy doesn't declare * support for it */ - if (sid == SECINITSID_INIT && !isid_init_supported) + if (sid == SECINITSID_INIT && !isid_init) continue; rc = sidtab_set_initial(s, sid, &c->context[0]); @@ -905,8 +905,9 @@ int policydb_load_isids(struct policydb *p, struct sidtab *s) * started before policy load would initially get the context * corresponding to SECINITSID_KERNEL. */ - if (sid == SECINITSID_KERNEL && !isid_init_supported) { - rc = sidtab_set_initial(s, SECINITSID_INIT, &c->context[0]); + if (sid == SECINITSID_KERNEL && !isid_init) { + rc = sidtab_set_initial(s, SECINITSID_INIT, + &c->context[0]); if (rc) { pr_err("SELinux: unable to load initial SID %s.\n", name); @@ -1047,8 +1048,7 @@ out: * Read and validate a security context structure * from a policydb binary representation file. */ -static int context_read_and_validate(struct context *c, - struct policydb *p, +static int context_read_and_validate(struct context *c, struct policydb *p, void *fp) { __le32 buf[3]; @@ -1211,10 +1211,8 @@ static int type_set_read(struct type_set *t, void *fp) return 0; } - -static int read_cons_helper(struct policydb *p, - struct constraint_node **nodep, - u32 ncons, int allowxtarget, void *fp) +static int read_cons_helper(struct policydb *p, struct constraint_node **nodep, + u32 ncons, int allowxtarget, void *fp) { struct constraint_node *c, *lc; struct constraint_expr *e, *le; @@ -1284,8 +1282,9 @@ static int read_cons_helper(struct policydb *p, return rc; if (p->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES) { - e->type_names = kzalloc(sizeof - (*e->type_names), GFP_KERNEL); + e->type_names = + kzalloc(sizeof(*e->type_names), + GFP_KERNEL); if (!e->type_names) return -ENOMEM; type_set_init(e->type_names); @@ -1319,7 +1318,7 @@ static int class_read(struct policydb *p, struct symtab *s, void *fp) if (!cladatum) return -ENOMEM; - rc = next_entry(buf, fp, sizeof(u32)*6); + rc = next_entry(buf, fp, sizeof(u32) * 6); if (rc) goto bad; @@ -1345,8 +1344,8 @@ static int class_read(struct policydb *p, struct symtab *s, void *fp) goto bad; rc = -EINVAL; - cladatum->comdatum = symtab_search(&p->p_commons, - cladatum->comkey); + cladatum->comdatum = + symtab_search(&p->p_commons, cladatum->comkey); if (!cladatum->comdatum) { pr_err("SELinux: unknown common %s\n", cladatum->comkey); @@ -1369,8 +1368,8 @@ static int class_read(struct policydb *p, struct symtab *s, void *fp) if (rc) goto bad; ncons = le32_to_cpu(buf[0]); - rc = read_cons_helper(p, &cladatum->validatetrans, - ncons, 1, fp); + rc = read_cons_helper(p, &cladatum->validatetrans, ncons, 1, + fp); if (rc) goto bad; } @@ -1507,7 +1506,6 @@ bad: return rc; } - /* * Read a MLS level structure from a policydb binary * representation file. @@ -1659,8 +1657,9 @@ bad: return rc; } -static int (*const read_f[SYM_NUM]) (struct policydb *p, - struct symtab *s, void *fp) = { +/* clang-format off */ +static int (*const read_f[SYM_NUM])(struct policydb *p, struct symtab *s, + void *fp) = { common_read, class_read, role_read, @@ -1670,6 +1669,7 @@ static int (*const read_f[SYM_NUM]) (struct policydb *p, sens_read, cat_read, }; +/* clang-format on */ static int user_bounds_sanity_check(void *key, void *datum, void *datap) { @@ -1685,12 +1685,13 @@ static int user_bounds_sanity_check(void *key, void *datum, void *datap) if (++depth == POLICYDB_BOUNDS_MAXDEPTH) { pr_err("SELinux: user %s: " "too deep or looped boundary\n", - (char *) key); + (char *)key); return -EINVAL; } upper = p->user_val_to_struct[upper->bounds - 1]; - ebitmap_for_each_positive_bit(&user->roles, node, bit) { + ebitmap_for_each_positive_bit(&user->roles, node, bit) + { if (ebitmap_get_bit(&upper->roles, bit)) continue; @@ -1721,12 +1722,13 @@ static int role_bounds_sanity_check(void *key, void *datum, void *datap) if (++depth == POLICYDB_BOUNDS_MAXDEPTH) { pr_err("SELinux: role %s: " "too deep or looped bounds\n", - (char *) key); + (char *)key); return -EINVAL; } upper = p->role_val_to_struct[upper->bounds - 1]; - ebitmap_for_each_positive_bit(&role->types, node, bit) { + ebitmap_for_each_positive_bit(&role->types, node, bit) + { if (ebitmap_get_bit(&upper->types, bit)) continue; @@ -1754,7 +1756,7 @@ static int type_bounds_sanity_check(void *key, void *datum, void *datap) if (++depth == POLICYDB_BOUNDS_MAXDEPTH) { pr_err("SELinux: type %s: " "too deep or looped boundary\n", - (char *) key); + (char *)key); return -EINVAL; } @@ -1764,7 +1766,7 @@ static int type_bounds_sanity_check(void *key, void *datum, void *datap) if (upper->attribute) { pr_err("SELinux: type %s: " "bounded by attribute %s\n", - (char *) key, + (char *)key, sym_name(p, SYM_TYPES, upper->value - 1)); return -EINVAL; } @@ -1815,7 +1817,7 @@ u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name) if (!tclass || tclass > p->p_classes.nprim) return 0; - cladatum = p->class_val_to_struct[tclass-1]; + cladatum = p->class_val_to_struct[tclass - 1]; comdatum = cladatum->comdatum; if (comdatum) perdatum = symtab_search(&comdatum->permissions, name); @@ -1824,7 +1826,7 @@ u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name) if (!perdatum) return 0; - return 1U << (perdatum->value-1); + return 1U << (perdatum->value - 1); } static int range_read(struct policydb *p, void *fp) @@ -2192,12 +2194,12 @@ static int genfs_read(struct policydb *p, void *fp) goto out; newc->v.sclass = le32_to_cpu(buf[0]); - rc = context_read_and_validate(&newc->context[0], p, fp); + rc = context_read_and_validate(&newc->context[0], p, + fp); if (rc) goto out; - for (l = NULL, c = genfs->head; c; - l = c, c = c->next) { + for (l = NULL, c = genfs->head; c; l = c, c = c->next) { rc = -EINVAL; if (!strcmp(newc->u.name, c->u.name) && (!c->v.sclass || !newc->v.sclass || @@ -2231,8 +2233,8 @@ out: return rc; } -static int ocontext_read(struct policydb *p, const struct policydb_compat_info *info, - void *fp) +static int ocontext_read(struct policydb *p, + const struct policydb_compat_info *info, void *fp) { int rc; unsigned int i; @@ -2267,7 +2269,8 @@ static int ocontext_read(struct policydb *p, const struct policydb_compat_info * goto out; c->sid[0] = le32_to_cpu(buf[0]); - rc = context_read_and_validate(&c->context[0], p, fp); + rc = context_read_and_validate(&c->context[0], + p, fp); if (rc) goto out; break; @@ -2286,21 +2289,24 @@ static int ocontext_read(struct policydb *p, const struct policydb_compat_info * pr_warn("SELinux: void and deprecated fs ocon %s\n", c->u.name); - rc = context_read_and_validate(&c->context[0], p, fp); + rc = context_read_and_validate(&c->context[0], + p, fp); if (rc) goto out; - rc = context_read_and_validate(&c->context[1], p, fp); + rc = context_read_and_validate(&c->context[1], + p, fp); if (rc) goto out; break; case OCON_PORT: - rc = next_entry(buf, fp, sizeof(u32)*3); + rc = next_entry(buf, fp, sizeof(u32) * 3); if (rc) goto out; c->u.port.protocol = le32_to_cpu(buf[0]); c->u.port.low_port = le32_to_cpu(buf[1]); c->u.port.high_port = le32_to_cpu(buf[2]); - rc = context_read_and_validate(&c->context[0], p, fp); + rc = context_read_and_validate(&c->context[0], + p, fp); if (rc) goto out; break; @@ -2310,12 +2316,13 @@ static int ocontext_read(struct policydb *p, const struct policydb_compat_info * goto out; c->u.node.addr = nodebuf[0]; /* network order */ c->u.node.mask = nodebuf[1]; /* network order */ - rc = context_read_and_validate(&c->context[0], p, fp); + rc = context_read_and_validate(&c->context[0], + p, fp); if (rc) goto out; break; case OCON_FSUSE: - rc = next_entry(buf, fp, sizeof(u32)*2); + rc = next_entry(buf, fp, sizeof(u32) * 2); if (rc) goto out; @@ -2332,7 +2339,8 @@ static int ocontext_read(struct policydb *p, const struct policydb_compat_info * if (rc) goto out; - rc = context_read_and_validate(&c->context[0], p, fp); + rc = context_read_and_validate(&c->context[0], + p, fp); if (rc) goto out; break; @@ -2345,8 +2353,9 @@ static int ocontext_read(struct policydb *p, const struct policydb_compat_info * for (k = 0; k < 4; k++) c->u.node6.addr[k] = nodebuf[k]; for (k = 0; k < 4; k++) - c->u.node6.mask[k] = nodebuf[k+4]; - rc = context_read_and_validate(&c->context[0], p, fp); + c->u.node6.mask[k] = nodebuf[k + 4]; + rc = context_read_and_validate(&c->context[0], + p, fp); if (rc) goto out; break; @@ -2359,7 +2368,8 @@ static int ocontext_read(struct policydb *p, const struct policydb_compat_info * goto out; /* we need to have subnet_prefix in CPU order */ - c->u.ibpkey.subnet_prefix = be64_to_cpu(prefixbuf[0]); + c->u.ibpkey.subnet_prefix = + be64_to_cpu(prefixbuf[0]); rc = next_entry(buf, fp, sizeof(u32) * 2); if (rc) @@ -2373,12 +2383,11 @@ static int ocontext_read(struct policydb *p, const struct policydb_compat_info * goto out; } - c->u.ibpkey.low_pkey = pkey_lo; + c->u.ibpkey.low_pkey = pkey_lo; c->u.ibpkey.high_pkey = pkey_hi; rc = context_read_and_validate(&c->context[0], - p, - fp); + p, fp); if (rc) goto out; break; @@ -2391,7 +2400,8 @@ static int ocontext_read(struct policydb *p, const struct policydb_compat_info * goto out; len = le32_to_cpu(buf[0]); - rc = str_read(&c->u.ibendport.dev_name, GFP_KERNEL, fp, len); + rc = str_read(&c->u.ibendport.dev_name, + GFP_KERNEL, fp, len); if (rc) goto out; @@ -2404,8 +2414,7 @@ static int ocontext_read(struct policydb *p, const struct policydb_compat_info * c->u.ibendport.port = port; rc = context_read_and_validate(&c->context[0], - p, - fp); + p, fp); if (rc) goto out; break; @@ -2462,7 +2471,8 @@ int policydb_read(struct policydb *p, void *fp) policydb_str = kmalloc(len + 1, GFP_KERNEL); if (!policydb_str) { pr_err("SELinux: unable to allocate memory for policydb " - "string of length %d\n", len); + "string of length %d\n", + len); goto bad; } @@ -2477,7 +2487,8 @@ int policydb_read(struct policydb *p, void *fp) policydb_str[len] = '\0'; if (strcmp(policydb_str, POLICYDB_STRING)) { pr_err("SELinux: policydb string %s does not match " - "my string %s\n", policydb_str, POLICYDB_STRING); + "my string %s\n", + policydb_str, POLICYDB_STRING); kfree(policydb_str); goto bad; } @@ -2486,7 +2497,7 @@ int policydb_read(struct policydb *p, void *fp) policydb_str = NULL; /* Read the version and table sizes. */ - rc = next_entry(buf, fp, sizeof(u32)*4); + rc = next_entry(buf, fp, sizeof(u32) * 4); if (rc) goto bad; @@ -2496,7 +2507,8 @@ int policydb_read(struct policydb *p, void *fp) p->policyvers > POLICYDB_VERSION_MAX) { pr_err("SELinux: policydb version %d does not match " "my version range %d-%d\n", - le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); + le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, + POLICYDB_VERSION_MAX); goto bad; } @@ -2506,8 +2518,8 @@ int policydb_read(struct policydb *p, void *fp) rc = -EINVAL; if (p->policyvers < POLICYDB_VERSION_MLS) { pr_err("SELinux: security policydb version %d " - "(MLS) not backwards compatible\n", - p->policyvers); + "(MLS) not backwards compatible\n", + p->policyvers); goto bad; } } @@ -2530,22 +2542,23 @@ int policydb_read(struct policydb *p, void *fp) info = policydb_lookup_compat(p->policyvers); if (!info) { pr_err("SELinux: unable to find policy compat info " - "for version %d\n", p->policyvers); + "for version %d\n", + p->policyvers); goto bad; } rc = -EINVAL; if (le32_to_cpu(buf[2]) != info->sym_num || - le32_to_cpu(buf[3]) != info->ocon_num) { + le32_to_cpu(buf[3]) != info->ocon_num) { pr_err("SELinux: policydb table sizes (%d,%d) do " - "not match mine (%d,%d)\n", le32_to_cpu(buf[2]), - le32_to_cpu(buf[3]), - info->sym_num, info->ocon_num); + "not match mine (%d,%d)\n", + le32_to_cpu(buf[2]), le32_to_cpu(buf[3]), info->sym_num, + info->ocon_num); goto bad; } for (i = 0; i < info->sym_num; i++) { - rc = next_entry(buf, fp, sizeof(u32)*2); + rc = next_entry(buf, fp, sizeof(u32) * 2); if (rc) goto bad; nprim = le32_to_cpu(buf[0]); @@ -2606,7 +2619,7 @@ int policydb_read(struct policydb *p, void *fp) if (!rtd) goto bad; - rc = next_entry(buf, fp, sizeof(u32)*3); + rc = next_entry(buf, fp, sizeof(u32) * 3); if (rc) goto bad; @@ -2650,7 +2663,7 @@ int policydb_read(struct policydb *p, void *fp) lra->next = ra; else p->role_allow = ra; - rc = next_entry(buf, fp, sizeof(u32)*2); + rc = next_entry(buf, fp, sizeof(u32) * 2); if (rc) goto bad; @@ -2698,9 +2711,8 @@ int policydb_read(struct policydb *p, void *fp) goto bad; rc = -ENOMEM; - p->type_attr_map_array = kvcalloc(p->p_types.nprim, - sizeof(*p->type_attr_map_array), - GFP_KERNEL); + p->type_attr_map_array = kvcalloc( + p->p_types.nprim, sizeof(*p->type_attr_map_array), GFP_KERNEL); if (!p->type_attr_map_array) goto bad; @@ -2773,7 +2785,7 @@ static int mls_write_range_helper(struct mls_range *r, void *fp) items = 2; else items = 3; - buf[0] = cpu_to_le32(items-1); + buf[0] = cpu_to_le32(items - 1); buf[1] = cpu_to_le32(r->level[0].sens); if (!eq) buf[2] = cpu_to_le32(r->level[1].sens); @@ -2916,8 +2928,7 @@ static int role_allow_write(struct role_allow *r, void *fp) * Write a security context structure * to a policydb binary representation file. */ -static int context_write(struct policydb *p, struct context *c, - void *fp) +static int context_write(struct policydb *p, struct context *c, void *fp) { int rc; __le32 buf[3]; @@ -3045,7 +3056,7 @@ static int write_cons_helper(struct policydb *p, struct constraint_node *node, if (rc) return rc; if (p->policyvers >= - POLICYDB_VERSION_CONSTRAINT_NAMES) { + POLICYDB_VERSION_CONSTRAINT_NAMES) { rc = type_set_write(e->type_names, fp); if (rc) return rc; @@ -3266,7 +3277,8 @@ static int user_write(void *vkey, void *datum, void *ptr) return 0; } -static int (*const write_f[SYM_NUM]) (void *key, void *datum, void *datap) = { +/* clang-format off */ +static int (*const write_f[SYM_NUM])(void *key, void *datum, void *datap) = { common_write, class_write, role_write, @@ -3276,9 +3288,10 @@ static int (*const write_f[SYM_NUM]) (void *key, void *datum, void *datap) = { sens_write, cat_write, }; +/* clang-format on */ -static int ocontext_write(struct policydb *p, const struct policydb_compat_info *info, - void *fp) +static int ocontext_write(struct policydb *p, + const struct policydb_compat_info *info, void *fp) { unsigned int i, j; int rc; @@ -3360,9 +3373,13 @@ static int ocontext_write(struct policydb *p, const struct policydb_compat_info break; case OCON_NODE6: for (j = 0; j < 4; j++) - nodebuf[j] = c->u.node6.addr[j]; /* network order */ + nodebuf[j] = + c->u.node6.addr + [j]; /* network order */ for (j = 0; j < 4; j++) - nodebuf[j + 4] = c->u.node6.mask[j]; /* network order */ + nodebuf[j + 4] = + c->u.node6.mask + [j]; /* network order */ rc = put_entry(nodebuf, sizeof(u32), 8, fp); if (rc) return rc; @@ -3372,7 +3389,8 @@ static int ocontext_write(struct policydb *p, const struct policydb_compat_info break; case OCON_IBPKEY: /* subnet_prefix is in CPU order */ - prefixbuf[0] = cpu_to_be64(c->u.ibpkey.subnet_prefix); + prefixbuf[0] = + cpu_to_be64(c->u.ibpkey.subnet_prefix); rc = put_entry(prefixbuf, sizeof(u64), 1, fp); if (rc) @@ -3395,7 +3413,8 @@ static int ocontext_write(struct policydb *p, const struct policydb_compat_info rc = put_entry(buf, sizeof(u32), 2, fp); if (rc) return rc; - rc = put_entry(c->u.ibendport.dev_name, 1, len, fp); + rc = put_entry(c->u.ibendport.dev_name, 1, len, + fp); if (rc) return rc; rc = context_write(p, &c->context[0], fp); @@ -3521,7 +3540,8 @@ static int filename_write_helper_compat(void *key, void *data, void *ptr) u32 bit, len = strlen(ft->name); do { - ebitmap_for_each_positive_bit(&datum->stypes, node, bit) { + ebitmap_for_each_positive_bit(&datum->stypes, node, bit) + { buf[0] = cpu_to_le32(len); rc = put_entry(buf, sizeof(u32), 1, fp); if (rc) @@ -3645,8 +3665,8 @@ int policydb_write(struct policydb *p, void *fp) */ if (p->policyvers < POLICYDB_VERSION_AVTAB) { pr_err("SELinux: refusing to write policy version %d." - " Because it is less than version %d\n", p->policyvers, - POLICYDB_VERSION_AVTAB); + " Because it is less than version %d\n", + p->policyvers, POLICYDB_VERSION_AVTAB); return -EINVAL; } @@ -3674,7 +3694,8 @@ int policydb_write(struct policydb *p, void *fp) info = policydb_lookup_compat(p->policyvers); if (!info) { pr_err("SELinux: compatibility lookup failed for policy " - "version %d\n", p->policyvers); + "version %d\n", + p->policyvers); return -EINVAL; } -- cgit v1.2.3 From 317e02905afdc8d88d6dbab9142a156d17b3ec62 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 22 Feb 2024 18:52:35 -0500 Subject: selinux: fix style issues in security/selinux/ss/services.h As part of on ongoing effort to perform more automated testing and provide more tools for individual developers to validate their patches before submitting, we are trying to make our code "clang-format clean". My hope is that once we have fixed all of our style "quirks", developers will be able to run clang-format on their patches to help avoid silly formatting problems and ensure their changes fit in well with the rest of the SELinux kernel code. Signed-off-by: Paul Moore --- security/selinux/ss/services.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'security') diff --git a/security/selinux/ss/services.h b/security/selinux/ss/services.h index d24b0a3d198e..93358e7a649c 100644 --- a/security/selinux/ss/services.h +++ b/security/selinux/ss/services.h @@ -4,6 +4,7 @@ * * Author : Stephen Smalley, */ + #ifndef _SS_SERVICES_H_ #define _SS_SERVICES_H_ @@ -43,4 +44,4 @@ int services_convert_context(struct convert_context_args *args, struct context *oldc, struct context *newc, gfp_t gfp_flags); -#endif /* _SS_SERVICES_H_ */ +#endif /* _SS_SERVICES_H_ */ -- cgit v1.2.3 From 72a1c577d11936e33fbe3238021ade7201223b89 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 22 Feb 2024 18:52:36 -0500 Subject: selinux: fix style issues in security/selinux/ss/sidtab.h As part of on ongoing effort to perform more automated testing and provide more tools for individual developers to validate their patches before submitting, we are trying to make our code "clang-format clean". My hope is that once we have fixed all of our style "quirks", developers will be able to run clang-format on their patches to help avoid silly formatting problems and ensure their changes fit in well with the rest of the SELinux kernel code. Signed-off-by: Paul Moore --- security/selinux/ss/sidtab.h | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/sidtab.h b/security/selinux/ss/sidtab.h index 22258201cd14..832c85c70d83 100644 --- a/security/selinux/ss/sidtab.h +++ b/security/selinux/ss/sidtab.h @@ -8,6 +8,7 @@ * * Copyright (C) 2018 Red Hat, Inc. */ + #ifndef _SS_SIDTAB_H_ #define _SS_SIDTAB_H_ @@ -29,25 +30,26 @@ struct sidtab_entry { union sidtab_entry_inner { struct sidtab_node_inner *ptr_inner; - struct sidtab_node_leaf *ptr_leaf; + struct sidtab_node_leaf *ptr_leaf; }; /* align node size to page boundary */ #define SIDTAB_NODE_ALLOC_SHIFT PAGE_SHIFT -#define SIDTAB_NODE_ALLOC_SIZE PAGE_SIZE +#define SIDTAB_NODE_ALLOC_SIZE PAGE_SIZE -#define size_to_shift(size) ((size) == 1 ? 1 : (const_ilog2((size) - 1) + 1)) +#define size_to_shift(size) ((size) == 1 ? 1 : (const_ilog2((size)-1) + 1)) -#define SIDTAB_INNER_SHIFT \ - (SIDTAB_NODE_ALLOC_SHIFT - size_to_shift(sizeof(union sidtab_entry_inner))) +#define SIDTAB_INNER_SHIFT \ + (SIDTAB_NODE_ALLOC_SHIFT - \ + size_to_shift(sizeof(union sidtab_entry_inner))) #define SIDTAB_INNER_ENTRIES ((size_t)1 << SIDTAB_INNER_SHIFT) #define SIDTAB_LEAF_ENTRIES \ (SIDTAB_NODE_ALLOC_SIZE / sizeof(struct sidtab_entry)) #define SIDTAB_MAX_BITS 32 -#define SIDTAB_MAX U32_MAX +#define SIDTAB_MAX U32_MAX /* ensure enough tree levels for SIDTAB_MAX entries */ -#define SIDTAB_MAX_LEVEL \ +#define SIDTAB_MAX_LEVEL \ DIV_ROUND_UP(SIDTAB_MAX_BITS - size_to_shift(SIDTAB_LEAF_ENTRIES), \ SIDTAB_INNER_SHIFT) @@ -69,7 +71,7 @@ struct sidtab_convert_params { struct sidtab *target; }; -#define SIDTAB_HASH_BITS CONFIG_SECURITY_SELINUX_SIDTAB_HASH_BITS +#define SIDTAB_HASH_BITS CONFIG_SECURITY_SELINUX_SIDTAB_HASH_BITS #define SIDTAB_HASH_BUCKETS (1 << SIDTAB_HASH_BITS) struct sidtab { @@ -125,8 +127,10 @@ int sidtab_convert(struct sidtab *s, struct sidtab_convert_params *params); void sidtab_cancel_convert(struct sidtab *s); -void sidtab_freeze_begin(struct sidtab *s, unsigned long *flags) __acquires(&s->lock); -void sidtab_freeze_end(struct sidtab *s, unsigned long *flags) __releases(&s->lock); +void sidtab_freeze_begin(struct sidtab *s, unsigned long *flags) + __acquires(&s->lock); +void sidtab_freeze_end(struct sidtab *s, unsigned long *flags) + __releases(&s->lock); int sidtab_context_to_sid(struct sidtab *s, struct context *context, u32 *sid); @@ -137,8 +141,8 @@ int sidtab_hash_stats(struct sidtab *sidtab, char *page); #if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 void sidtab_sid2str_put(struct sidtab *s, struct sidtab_entry *entry, const char *str, u32 str_len); -int sidtab_sid2str_get(struct sidtab *s, struct sidtab_entry *entry, - char **out, u32 *out_len); +int sidtab_sid2str_get(struct sidtab *s, struct sidtab_entry *entry, char **out, + u32 *out_len); #else static inline void sidtab_sid2str_put(struct sidtab *s, struct sidtab_entry *entry, @@ -146,13 +150,11 @@ static inline void sidtab_sid2str_put(struct sidtab *s, { } static inline int sidtab_sid2str_get(struct sidtab *s, - struct sidtab_entry *entry, - char **out, u32 *out_len) + struct sidtab_entry *entry, char **out, + u32 *out_len) { return -ENOENT; } #endif /* CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 */ -#endif /* _SS_SIDTAB_H_ */ - - +#endif /* _SS_SIDTAB_H_ */ -- cgit v1.2.3 From dc9a746798263d300ff7a9968042e7977f2fff02 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 22 Feb 2024 18:52:37 -0500 Subject: selinux: fix style issues in security/selinux/ss/sidtab.c As part of on ongoing effort to perform more automated testing and provide more tools for individual developers to validate their patches before submitting, we are trying to make our code "clang-format clean". My hope is that once we have fixed all of our style "quirks", developers will be able to run clang-format on their patches to help avoid silly formatting problems and ensure their changes fit in well with the rest of the SELinux kernel code. Signed-off-by: Paul Moore --- security/selinux/ss/sidtab.c | 69 ++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 32 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c index 732fd8e22a12..c8848cbba81f 100644 --- a/security/selinux/ss/sidtab.c +++ b/security/selinux/ss/sidtab.c @@ -7,6 +7,7 @@ * * Copyright (C) 2018 Red Hat, Inc. */ + #include #include #include @@ -29,7 +30,7 @@ struct sidtab_str_cache { }; #define index_to_sid(index) ((index) + SECINITSID_NUM + 1) -#define sid_to_index(sid) ((sid) - (SECINITSID_NUM + 1)) +#define sid_to_index(sid) ((sid) - (SECINITSID_NUM + 1)) int sidtab_init(struct sidtab *s) { @@ -140,9 +141,11 @@ int sidtab_hash_stats(struct sidtab *sidtab, char *page) if (chain_len > max_chain_len) max_chain_len = chain_len; - return scnprintf(page, PAGE_SIZE, "entries: %d\nbuckets used: %d/%d\n" - "longest chain: %d\n", entries, - slots_used, SIDTAB_HASH_BUCKETS, max_chain_len); + return scnprintf(page, PAGE_SIZE, + "entries: %d\nbuckets used: %d/%d\n" + "longest chain: %d\n", + entries, slots_used, SIDTAB_HASH_BUCKETS, + max_chain_len); } static u32 sidtab_level_from_count(u32 count) @@ -162,15 +165,15 @@ static int sidtab_alloc_roots(struct sidtab *s, u32 level) u32 l; if (!s->roots[0].ptr_leaf) { - s->roots[0].ptr_leaf = kzalloc(SIDTAB_NODE_ALLOC_SIZE, - GFP_ATOMIC); + s->roots[0].ptr_leaf = + kzalloc(SIDTAB_NODE_ALLOC_SIZE, GFP_ATOMIC); if (!s->roots[0].ptr_leaf) return -ENOMEM; } for (l = 1; l <= level; ++l) if (!s->roots[l].ptr_inner) { - s->roots[l].ptr_inner = kzalloc(SIDTAB_NODE_ALLOC_SIZE, - GFP_ATOMIC); + s->roots[l].ptr_inner = + kzalloc(SIDTAB_NODE_ALLOC_SIZE, GFP_ATOMIC); if (!s->roots[l].ptr_inner) return -ENOMEM; s->roots[l].ptr_inner->entries[0] = s->roots[l - 1]; @@ -203,16 +206,16 @@ static struct sidtab_entry *sidtab_do_lookup(struct sidtab *s, u32 index, if (!entry->ptr_inner) { if (alloc) - entry->ptr_inner = kzalloc(SIDTAB_NODE_ALLOC_SIZE, - GFP_ATOMIC); + entry->ptr_inner = kzalloc( + SIDTAB_NODE_ALLOC_SIZE, GFP_ATOMIC); if (!entry->ptr_inner) return NULL; } } if (!entry->ptr_leaf) { if (alloc) - entry->ptr_leaf = kzalloc(SIDTAB_NODE_ALLOC_SIZE, - GFP_ATOMIC); + entry->ptr_leaf = + kzalloc(SIDTAB_NODE_ALLOC_SIZE, GFP_ATOMIC); if (!entry->ptr_leaf) return NULL; } @@ -262,8 +265,7 @@ struct sidtab_entry *sidtab_search_entry_force(struct sidtab *s, u32 sid) return sidtab_search_core(s, sid, 1); } -int sidtab_context_to_sid(struct sidtab *s, struct context *context, - u32 *sid) +int sidtab_context_to_sid(struct sidtab *s, struct context *context, u32 *sid) { unsigned long flags; u32 count, hash = context_compute_hash(context); @@ -327,8 +329,8 @@ int sidtab_context_to_sid(struct sidtab *s, struct context *context, goto out_unlock; } - rc = services_convert_context(convert->args, - context, &dst_convert->context, + rc = services_convert_context(convert->args, context, + &dst_convert->context, GFP_ATOMIC); if (rc) { context_destroy(&dst->context); @@ -338,8 +340,8 @@ int sidtab_context_to_sid(struct sidtab *s, struct context *context, dst_convert->hash = context_compute_hash(&dst_convert->context); target->count = count + 1; - hash_add_rcu(target->context_to_sid, - &dst_convert->list, dst_convert->hash); + hash_add_rcu(target->context_to_sid, &dst_convert->list, + dst_convert->hash); } if (context->len) @@ -373,8 +375,8 @@ static void sidtab_convert_hashtable(struct sidtab *s, u32 count) } static int sidtab_convert_tree(union sidtab_entry_inner *edst, - union sidtab_entry_inner *esrc, - u32 *pos, u32 count, u32 level, + union sidtab_entry_inner *esrc, u32 *pos, + u32 count, u32 level, struct sidtab_convert_params *convert) { int rc; @@ -382,8 +384,8 @@ static int sidtab_convert_tree(union sidtab_entry_inner *edst, if (level != 0) { if (!edst->ptr_inner) { - edst->ptr_inner = kzalloc(SIDTAB_NODE_ALLOC_SIZE, - GFP_KERNEL); + edst->ptr_inner = + kzalloc(SIDTAB_NODE_ALLOC_SIZE, GFP_KERNEL); if (!edst->ptr_inner) return -ENOMEM; } @@ -399,17 +401,18 @@ static int sidtab_convert_tree(union sidtab_entry_inner *edst, } } else { if (!edst->ptr_leaf) { - edst->ptr_leaf = kzalloc(SIDTAB_NODE_ALLOC_SIZE, - GFP_KERNEL); + edst->ptr_leaf = + kzalloc(SIDTAB_NODE_ALLOC_SIZE, GFP_KERNEL); if (!edst->ptr_leaf) return -ENOMEM; } i = 0; while (i < SIDTAB_LEAF_ENTRIES && *pos < count) { - rc = services_convert_context(convert->args, - &esrc->ptr_leaf->entries[i].context, - &edst->ptr_leaf->entries[i].context, - GFP_KERNEL); + rc = services_convert_context( + convert->args, + &esrc->ptr_leaf->entries[i].context, + &edst->ptr_leaf->entries[i].context, + GFP_KERNEL); if (rc) return rc; (*pos)++; @@ -489,13 +492,15 @@ void sidtab_cancel_convert(struct sidtab *s) spin_unlock_irqrestore(&s->lock, flags); } -void sidtab_freeze_begin(struct sidtab *s, unsigned long *flags) __acquires(&s->lock) +void sidtab_freeze_begin(struct sidtab *s, unsigned long *flags) + __acquires(&s->lock) { spin_lock_irqsave(&s->lock, *flags); s->frozen = true; s->convert = NULL; } -void sidtab_freeze_end(struct sidtab *s, unsigned long *flags) __releases(&s->lock) +void sidtab_freeze_end(struct sidtab *s, unsigned long *flags) + __releases(&s->lock) { spin_unlock_irqrestore(&s->lock, *flags); } @@ -600,8 +605,8 @@ out_unlock: kfree_rcu(victim, rcu_member); } -int sidtab_sid2str_get(struct sidtab *s, struct sidtab_entry *entry, - char **out, u32 *out_len) +int sidtab_sid2str_get(struct sidtab *s, struct sidtab_entry *entry, char **out, + u32 *out_len) { struct sidtab_str_cache *cache; int rc = 0; -- cgit v1.2.3 From 5fca473c139693d01fcd8fbeb8c4907445934a64 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 22 Feb 2024 18:52:38 -0500 Subject: selinux: fix style issues in security/selinux/ss/symtab.h As part of on ongoing effort to perform more automated testing and provide more tools for individual developers to validate their patches before submitting, we are trying to make our code "clang-format clean". My hope is that once we have fixed all of our style "quirks", developers will be able to run clang-format on their patches to help avoid silly formatting problems and ensure their changes fit in well with the rest of the SELinux kernel code. Signed-off-by: Paul Moore --- security/selinux/ss/symtab.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'security') diff --git a/security/selinux/ss/symtab.h b/security/selinux/ss/symtab.h index 0a3b5de79a0f..8e667cdbf38f 100644 --- a/security/selinux/ss/symtab.h +++ b/security/selinux/ss/symtab.h @@ -7,14 +7,15 @@ * * Author : Stephen Smalley, */ + #ifndef _SS_SYMTAB_H_ #define _SS_SYMTAB_H_ #include "hashtab.h" struct symtab { - struct hashtab table; /* hash table (keyed on a string) */ - u32 nprim; /* number of primary names in table */ + struct hashtab table; /* hash table (keyed on a string) */ + u32 nprim; /* number of primary names in table */ }; int symtab_init(struct symtab *s, u32 size); @@ -22,6 +23,4 @@ int symtab_init(struct symtab *s, u32 size); int symtab_insert(struct symtab *s, char *name, void *datum); void *symtab_search(struct symtab *s, const char *name); -#endif /* _SS_SYMTAB_H_ */ - - +#endif /* _SS_SYMTAB_H_ */ -- cgit v1.2.3 From a1fc79343abbdc5bebb80c2a9032063442df8b59 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 22 Feb 2024 18:52:39 -0500 Subject: selinux: fix style issues in security/selinux/ss/symtab.c As part of on ongoing effort to perform more automated testing and provide more tools for individual developers to validate their patches before submitting, we are trying to make our code "clang-format clean". My hope is that once we have fixed all of our style "quirks", developers will be able to run clang-format on their patches to help avoid silly formatting problems and ensure their changes fit in well with the rest of the SELinux kernel code. Signed-off-by: Paul Moore --- security/selinux/ss/symtab.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'security') diff --git a/security/selinux/ss/symtab.c b/security/selinux/ss/symtab.c index 43d7f0319ccd..c04f8d447873 100644 --- a/security/selinux/ss/symtab.c +++ b/security/selinux/ss/symtab.c @@ -4,6 +4,7 @@ * * Author : Stephen Smalley, */ + #include #include #include @@ -19,7 +20,8 @@ static unsigned int symhash(const void *key) keyp = key; size = strlen(keyp); for (p = keyp; (p - keyp) < size; p++) - val = (val << 4 | (val >> (8*sizeof(unsigned int)-4))) ^ (*p); + val = (val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ + (*p); return val; } -- cgit v1.2.3 From d9818b3e906a0ee1ab02ea79e74a2f755fc5461a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= Date: Mon, 19 Feb 2024 20:03:45 +0100 Subject: landlock: Fix asymmetric private inodes referring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When linking or renaming a file, if only one of the source or destination directory is backed by an S_PRIVATE inode, then the related set of layer masks would be used as uninitialized by is_access_to_paths_allowed(). This would result to indeterministic access for one side instead of always being allowed. This bug could only be triggered with a mounted filesystem containing both S_PRIVATE and !S_PRIVATE inodes, which doesn't seem possible. The collect_domain_accesses() calls return early if is_nouser_or_private() returns false, which means that the directory's superblock has SB_NOUSER or its inode has S_PRIVATE. Because rename or link actions are only allowed on the same mounted filesystem, the superblock is always the same for both source and destination directories. However, it might be possible in theory to have an S_PRIVATE parent source inode with an !S_PRIVATE parent destination inode, or vice versa. To make sure this case is not an issue, explicitly initialized both set of layer masks to 0, which means to allow all actions on the related side. If at least on side has !S_PRIVATE, then collect_domain_accesses() and is_access_to_paths_allowed() check for the required access rights. Cc: Arnd Bergmann Cc: Christian Brauner Cc: Günther Noack Cc: Jann Horn Cc: Shervin Oloumi Cc: stable@vger.kernel.org Fixes: b91c3e4ea756 ("landlock: Add support for file reparenting with LANDLOCK_ACCESS_FS_REFER") Link: https://lore.kernel.org/r/20240219190345.2928627-1-mic@digikod.net Signed-off-by: Mickaël Salaün --- security/landlock/fs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/security/landlock/fs.c b/security/landlock/fs.c index fc520a06f9af..0171f7eb6ee1 100644 --- a/security/landlock/fs.c +++ b/security/landlock/fs.c @@ -737,8 +737,8 @@ static int current_check_refer_path(struct dentry *const old_dentry, bool allow_parent1, allow_parent2; access_mask_t access_request_parent1, access_request_parent2; struct path mnt_dir; - layer_mask_t layer_masks_parent1[LANDLOCK_NUM_ACCESS_FS], - layer_masks_parent2[LANDLOCK_NUM_ACCESS_FS]; + layer_mask_t layer_masks_parent1[LANDLOCK_NUM_ACCESS_FS] = {}, + layer_masks_parent2[LANDLOCK_NUM_ACCESS_FS] = {}; if (!dom) return 0; -- cgit v1.2.3 From b4007fd27206c478a4b76e299bddf4a71787f520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= Date: Thu, 18 Jan 2024 12:36:32 +0100 Subject: landlock: Add support for KUnit tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the SECURITY_LANDLOCK_KUNIT_TEST option to enable KUnit tests for Landlock. The minimal required configuration is listed in the security/landlock/.kunitconfig file. Add an initial landlock_fs KUnit test suite with 7 test cases for filesystem helpers. These are related to the LANDLOCK_ACCESS_FS_REFER right. There is one KUnit test case per: * mutated state (e.g. test_scope_to_request_*) or, * shared state between tests (e.g. test_is_eaccess_*). Add macros to improve readability of tests (i.e. one per line). Test cases are collocated with the tested functions to help maintenance and improve documentation. This is why SECURITY_LANDLOCK_KUNIT_TEST cannot be set as module. This is a nice complement to Landlock's user space kselftests. We expect new Landlock features to come with KUnit tests as well. Thanks to UML support, we can run all KUnit tests for Landlock with: ./tools/testing/kunit/kunit.py run --kunitconfig security/landlock [00:00:00] ======================= landlock_fs ======================= [00:00:00] [PASSED] test_no_more_access [00:00:00] [PASSED] test_scope_to_request_with_exec_none [00:00:00] [PASSED] test_scope_to_request_with_exec_some [00:00:00] [PASSED] test_scope_to_request_without_access [00:00:00] [PASSED] test_is_eacces_with_none [00:00:00] [PASSED] test_is_eacces_with_refer [00:00:00] [PASSED] test_is_eacces_with_write [00:00:00] =================== [PASSED] landlock_fs =================== [00:00:00] ============================================================ [00:00:00] Testing complete. Ran 7 tests: passed: 7 Cc: Konstantin Meskhidze Reviewed-by: Günther Noack Link: https://lore.kernel.org/r/20240118113632.1948478-1-mic@digikod.net Signed-off-by: Mickaël Salaün --- security/landlock/.kunitconfig | 4 + security/landlock/Kconfig | 15 +++ security/landlock/common.h | 2 + security/landlock/fs.c | 234 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 255 insertions(+) create mode 100644 security/landlock/.kunitconfig (limited to 'security') diff --git a/security/landlock/.kunitconfig b/security/landlock/.kunitconfig new file mode 100644 index 000000000000..03e119466604 --- /dev/null +++ b/security/landlock/.kunitconfig @@ -0,0 +1,4 @@ +CONFIG_KUNIT=y +CONFIG_SECURITY=y +CONFIG_SECURITY_LANDLOCK=y +CONFIG_SECURITY_LANDLOCK_KUNIT_TEST=y diff --git a/security/landlock/Kconfig b/security/landlock/Kconfig index c4bf0d5eff39..3f1493402052 100644 --- a/security/landlock/Kconfig +++ b/security/landlock/Kconfig @@ -20,3 +20,18 @@ config SECURITY_LANDLOCK If you are unsure how to answer this question, answer N. Otherwise, you should also prepend "landlock," to the content of CONFIG_LSM to enable Landlock at boot time. + +config SECURITY_LANDLOCK_KUNIT_TEST + bool "KUnit tests for Landlock" if !KUNIT_ALL_TESTS + depends on KUNIT=y + depends on SECURITY_LANDLOCK + default KUNIT_ALL_TESTS + help + Build KUnit tests for Landlock. + + See the KUnit documentation in Documentation/dev-tools/kunit + + Run all KUnit tests for Landlock with: + ./tools/testing/kunit/kunit.py run --kunitconfig security/landlock + + If you are unsure how to answer this question, answer N. diff --git a/security/landlock/common.h b/security/landlock/common.h index 5dc0fe15707d..0eb1d34c2eae 100644 --- a/security/landlock/common.h +++ b/security/landlock/common.h @@ -17,4 +17,6 @@ #define pr_fmt(fmt) LANDLOCK_NAME ": " fmt +#define BIT_INDEX(bit) HWEIGHT(bit - 1) + #endif /* _SECURITY_LANDLOCK_COMMON_H */ diff --git a/security/landlock/fs.c b/security/landlock/fs.c index 0171f7eb6ee1..6f0bf1434a2c 100644 --- a/security/landlock/fs.c +++ b/security/landlock/fs.c @@ -7,6 +7,7 @@ * Copyright © 2021-2022 Microsoft Corporation */ +#include #include #include #include @@ -311,6 +312,119 @@ static bool no_more_access( return true; } +#define NMA_TRUE(...) KUNIT_EXPECT_TRUE(test, no_more_access(__VA_ARGS__)) +#define NMA_FALSE(...) KUNIT_EXPECT_FALSE(test, no_more_access(__VA_ARGS__)) + +#ifdef CONFIG_SECURITY_LANDLOCK_KUNIT_TEST + +static void test_no_more_access(struct kunit *const test) +{ + const layer_mask_t rx0[LANDLOCK_NUM_ACCESS_FS] = { + [BIT_INDEX(LANDLOCK_ACCESS_FS_EXECUTE)] = BIT_ULL(0), + [BIT_INDEX(LANDLOCK_ACCESS_FS_READ_FILE)] = BIT_ULL(0), + }; + const layer_mask_t mx0[LANDLOCK_NUM_ACCESS_FS] = { + [BIT_INDEX(LANDLOCK_ACCESS_FS_EXECUTE)] = BIT_ULL(0), + [BIT_INDEX(LANDLOCK_ACCESS_FS_MAKE_REG)] = BIT_ULL(0), + }; + const layer_mask_t x0[LANDLOCK_NUM_ACCESS_FS] = { + [BIT_INDEX(LANDLOCK_ACCESS_FS_EXECUTE)] = BIT_ULL(0), + }; + const layer_mask_t x1[LANDLOCK_NUM_ACCESS_FS] = { + [BIT_INDEX(LANDLOCK_ACCESS_FS_EXECUTE)] = BIT_ULL(1), + }; + const layer_mask_t x01[LANDLOCK_NUM_ACCESS_FS] = { + [BIT_INDEX(LANDLOCK_ACCESS_FS_EXECUTE)] = BIT_ULL(0) | + BIT_ULL(1), + }; + const layer_mask_t allows_all[LANDLOCK_NUM_ACCESS_FS] = {}; + + /* Checks without restriction. */ + NMA_TRUE(&x0, &allows_all, false, &allows_all, NULL, false); + NMA_TRUE(&allows_all, &x0, false, &allows_all, NULL, false); + NMA_FALSE(&x0, &x0, false, &allows_all, NULL, false); + + /* + * Checks that we can only refer a file if no more access could be + * inherited. + */ + NMA_TRUE(&x0, &x0, false, &rx0, NULL, false); + NMA_TRUE(&rx0, &rx0, false, &rx0, NULL, false); + NMA_FALSE(&rx0, &rx0, false, &x0, NULL, false); + NMA_FALSE(&rx0, &rx0, false, &x1, NULL, false); + + /* Checks allowed referring with different nested domains. */ + NMA_TRUE(&x0, &x1, false, &x0, NULL, false); + NMA_TRUE(&x1, &x0, false, &x0, NULL, false); + NMA_TRUE(&x0, &x01, false, &x0, NULL, false); + NMA_TRUE(&x0, &x01, false, &rx0, NULL, false); + NMA_TRUE(&x01, &x0, false, &x0, NULL, false); + NMA_TRUE(&x01, &x0, false, &rx0, NULL, false); + NMA_FALSE(&x01, &x01, false, &x0, NULL, false); + + /* Checks that file access rights are also enforced for a directory. */ + NMA_FALSE(&rx0, &rx0, true, &x0, NULL, false); + + /* Checks that directory access rights don't impact file referring... */ + NMA_TRUE(&mx0, &mx0, false, &x0, NULL, false); + /* ...but only directory referring. */ + NMA_FALSE(&mx0, &mx0, true, &x0, NULL, false); + + /* Checks directory exchange. */ + NMA_TRUE(&mx0, &mx0, true, &mx0, &mx0, true); + NMA_TRUE(&mx0, &mx0, true, &mx0, &x0, true); + NMA_FALSE(&mx0, &mx0, true, &x0, &mx0, true); + NMA_FALSE(&mx0, &mx0, true, &x0, &x0, true); + NMA_FALSE(&mx0, &mx0, true, &x1, &x1, true); + + /* Checks file exchange with directory access rights... */ + NMA_TRUE(&mx0, &mx0, false, &mx0, &mx0, false); + NMA_TRUE(&mx0, &mx0, false, &mx0, &x0, false); + NMA_TRUE(&mx0, &mx0, false, &x0, &mx0, false); + NMA_TRUE(&mx0, &mx0, false, &x0, &x0, false); + /* ...and with file access rights. */ + NMA_TRUE(&rx0, &rx0, false, &rx0, &rx0, false); + NMA_TRUE(&rx0, &rx0, false, &rx0, &x0, false); + NMA_FALSE(&rx0, &rx0, false, &x0, &rx0, false); + NMA_FALSE(&rx0, &rx0, false, &x0, &x0, false); + NMA_FALSE(&rx0, &rx0, false, &x1, &x1, false); + + /* + * Allowing the following requests should not be a security risk + * because domain 0 denies execute access, and domain 1 is always + * nested with domain 0. However, adding an exception for this case + * would mean to check all nested domains to make sure none can get + * more privileges (e.g. processes only sandboxed by domain 0). + * Moreover, this behavior (i.e. composition of N domains) could then + * be inconsistent compared to domain 1's ruleset alone (e.g. it might + * be denied to link/rename with domain 1's ruleset, whereas it would + * be allowed if nested on top of domain 0). Another drawback would be + * to create a cover channel that could enable sandboxed processes to + * infer most of the filesystem restrictions from their domain. To + * make it simple, efficient, safe, and more consistent, this case is + * always denied. + */ + NMA_FALSE(&x1, &x1, false, &x0, NULL, false); + NMA_FALSE(&x1, &x1, false, &rx0, NULL, false); + NMA_FALSE(&x1, &x1, true, &x0, NULL, false); + NMA_FALSE(&x1, &x1, true, &rx0, NULL, false); + + /* Checks the same case of exclusive domains with a file... */ + NMA_TRUE(&x1, &x1, false, &x01, NULL, false); + NMA_FALSE(&x1, &x1, false, &x01, &x0, false); + NMA_FALSE(&x1, &x1, false, &x01, &x01, false); + NMA_FALSE(&x1, &x1, false, &x0, &x0, false); + /* ...and with a directory. */ + NMA_FALSE(&x1, &x1, false, &x0, &x0, true); + NMA_FALSE(&x1, &x1, true, &x0, &x0, false); + NMA_FALSE(&x1, &x1, true, &x0, &x0, true); +} + +#endif /* CONFIG_SECURITY_LANDLOCK_KUNIT_TEST */ + +#undef NMA_TRUE +#undef NMA_FALSE + /* * Removes @layer_masks accesses that are not requested. * @@ -331,6 +445,57 @@ scope_to_request(const access_mask_t access_request, return !memchr_inv(layer_masks, 0, sizeof(*layer_masks)); } +#ifdef CONFIG_SECURITY_LANDLOCK_KUNIT_TEST + +static void test_scope_to_request_with_exec_none(struct kunit *const test) +{ + /* Allows everything. */ + layer_mask_t layer_masks[LANDLOCK_NUM_ACCESS_FS] = {}; + + /* Checks and scopes with execute. */ + KUNIT_EXPECT_TRUE(test, scope_to_request(LANDLOCK_ACCESS_FS_EXECUTE, + &layer_masks)); + KUNIT_EXPECT_EQ(test, 0, + layer_masks[BIT_INDEX(LANDLOCK_ACCESS_FS_EXECUTE)]); + KUNIT_EXPECT_EQ(test, 0, + layer_masks[BIT_INDEX(LANDLOCK_ACCESS_FS_WRITE_FILE)]); +} + +static void test_scope_to_request_with_exec_some(struct kunit *const test) +{ + /* Denies execute and write. */ + layer_mask_t layer_masks[LANDLOCK_NUM_ACCESS_FS] = { + [BIT_INDEX(LANDLOCK_ACCESS_FS_EXECUTE)] = BIT_ULL(0), + [BIT_INDEX(LANDLOCK_ACCESS_FS_WRITE_FILE)] = BIT_ULL(1), + }; + + /* Checks and scopes with execute. */ + KUNIT_EXPECT_FALSE(test, scope_to_request(LANDLOCK_ACCESS_FS_EXECUTE, + &layer_masks)); + KUNIT_EXPECT_EQ(test, BIT_ULL(0), + layer_masks[BIT_INDEX(LANDLOCK_ACCESS_FS_EXECUTE)]); + KUNIT_EXPECT_EQ(test, 0, + layer_masks[BIT_INDEX(LANDLOCK_ACCESS_FS_WRITE_FILE)]); +} + +static void test_scope_to_request_without_access(struct kunit *const test) +{ + /* Denies execute and write. */ + layer_mask_t layer_masks[LANDLOCK_NUM_ACCESS_FS] = { + [BIT_INDEX(LANDLOCK_ACCESS_FS_EXECUTE)] = BIT_ULL(0), + [BIT_INDEX(LANDLOCK_ACCESS_FS_WRITE_FILE)] = BIT_ULL(1), + }; + + /* Checks and scopes without access request. */ + KUNIT_EXPECT_TRUE(test, scope_to_request(0, &layer_masks)); + KUNIT_EXPECT_EQ(test, 0, + layer_masks[BIT_INDEX(LANDLOCK_ACCESS_FS_EXECUTE)]); + KUNIT_EXPECT_EQ(test, 0, + layer_masks[BIT_INDEX(LANDLOCK_ACCESS_FS_WRITE_FILE)]); +} + +#endif /* CONFIG_SECURITY_LANDLOCK_KUNIT_TEST */ + /* * Returns true if there is at least one access right different than * LANDLOCK_ACCESS_FS_REFER. @@ -354,6 +519,51 @@ is_eacces(const layer_mask_t (*const layer_masks)[LANDLOCK_NUM_ACCESS_FS], return false; } +#define IE_TRUE(...) KUNIT_EXPECT_TRUE(test, is_eacces(__VA_ARGS__)) +#define IE_FALSE(...) KUNIT_EXPECT_FALSE(test, is_eacces(__VA_ARGS__)) + +#ifdef CONFIG_SECURITY_LANDLOCK_KUNIT_TEST + +static void test_is_eacces_with_none(struct kunit *const test) +{ + const layer_mask_t layer_masks[LANDLOCK_NUM_ACCESS_FS] = {}; + + IE_FALSE(&layer_masks, 0); + IE_FALSE(&layer_masks, LANDLOCK_ACCESS_FS_REFER); + IE_FALSE(&layer_masks, LANDLOCK_ACCESS_FS_EXECUTE); + IE_FALSE(&layer_masks, LANDLOCK_ACCESS_FS_WRITE_FILE); +} + +static void test_is_eacces_with_refer(struct kunit *const test) +{ + const layer_mask_t layer_masks[LANDLOCK_NUM_ACCESS_FS] = { + [BIT_INDEX(LANDLOCK_ACCESS_FS_REFER)] = BIT_ULL(0), + }; + + IE_FALSE(&layer_masks, 0); + IE_FALSE(&layer_masks, LANDLOCK_ACCESS_FS_REFER); + IE_FALSE(&layer_masks, LANDLOCK_ACCESS_FS_EXECUTE); + IE_FALSE(&layer_masks, LANDLOCK_ACCESS_FS_WRITE_FILE); +} + +static void test_is_eacces_with_write(struct kunit *const test) +{ + const layer_mask_t layer_masks[LANDLOCK_NUM_ACCESS_FS] = { + [BIT_INDEX(LANDLOCK_ACCESS_FS_WRITE_FILE)] = BIT_ULL(0), + }; + + IE_FALSE(&layer_masks, 0); + IE_FALSE(&layer_masks, LANDLOCK_ACCESS_FS_REFER); + IE_FALSE(&layer_masks, LANDLOCK_ACCESS_FS_EXECUTE); + + IE_TRUE(&layer_masks, LANDLOCK_ACCESS_FS_WRITE_FILE); +} + +#endif /* CONFIG_SECURITY_LANDLOCK_KUNIT_TEST */ + +#undef IE_TRUE +#undef IE_FALSE + /** * is_access_to_paths_allowed - Check accesses for requests with a common path * @@ -1225,3 +1435,27 @@ __init void landlock_add_fs_hooks(void) security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks), &landlock_lsmid); } + +#ifdef CONFIG_SECURITY_LANDLOCK_KUNIT_TEST + +/* clang-format off */ +static struct kunit_case test_cases[] = { + KUNIT_CASE(test_no_more_access), + KUNIT_CASE(test_scope_to_request_with_exec_none), + KUNIT_CASE(test_scope_to_request_with_exec_some), + KUNIT_CASE(test_scope_to_request_without_access), + KUNIT_CASE(test_is_eacces_with_none), + KUNIT_CASE(test_is_eacces_with_refer), + KUNIT_CASE(test_is_eacces_with_write), + {} +}; +/* clang-format on */ + +static struct kunit_suite test_suite = { + .name = "landlock_fs", + .test_cases = test_cases, +}; + +kunit_test_suite(test_suite); + +#endif /* CONFIG_SECURITY_LANDLOCK_KUNIT_TEST */ -- cgit v1.2.3 From 2f03fc340cac9ea1dc63cbf8c93dd2eb0f227815 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Fri, 1 Mar 2024 22:04:06 +0900 Subject: tomoyo: fix UAF write bug in tomoyo_write_control() Since tomoyo_write_control() updates head->write_buf when write() of long lines is requested, we need to fetch head->write_buf after head->io_sem is held. Otherwise, concurrent write() requests can cause use-after-free-write and double-free problems. Reported-by: Sam Sun Closes: https://lkml.kernel.org/r/CAEkJfYNDspuGxYx5kym8Lvp--D36CMDUErg4rxfWFJuPbbji8g@mail.gmail.com Fixes: bd03a3e4c9a9 ("TOMOYO: Add policy namespace support.") Cc: # Linux 3.1+ Signed-off-by: Tetsuo Handa Signed-off-by: Linus Torvalds --- security/tomoyo/common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'security') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 57ee70ae50f2..ea3140d510ec 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -2649,13 +2649,14 @@ ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head, { int error = buffer_len; size_t avail_len = buffer_len; - char *cp0 = head->write_buf; + char *cp0; int idx; if (!head->write) return -EINVAL; if (mutex_lock_interruptible(&head->io_sem)) return -EINTR; + cp0 = head->write_buf; head->read_user_buf_avail = 0; idx = tomoyo_read_lock(); /* Read a line and dispatch it to the policy handler. */ -- cgit v1.2.3 From 782191c74875cc33b50263e21d76080b1411884d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= Date: Tue, 27 Feb 2024 12:05:50 +0100 Subject: landlock: Warn once if a Landlock action is requested while disabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Because sandboxing can be used as an opportunistic security measure, user space may not log unsupported features. Let the system administrator know if an application tries to use Landlock but failed because it isn't enabled at boot time. This may be caused by boot loader configurations with outdated "lsm" kernel's command-line parameter. Cc: stable@vger.kernel.org Fixes: 265885daf3e5 ("landlock: Add syscall implementations") Reviewed-by: Kees Cook Reviewed-by: Günther Noack Link: https://lore.kernel.org/r/20240227110550.3702236-2-mic@digikod.net Signed-off-by: Mickaël Salaün --- security/landlock/syscalls.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'security') diff --git a/security/landlock/syscalls.c b/security/landlock/syscalls.c index 898358f57fa0..6788e73b6681 100644 --- a/security/landlock/syscalls.c +++ b/security/landlock/syscalls.c @@ -33,6 +33,18 @@ #include "ruleset.h" #include "setup.h" +static bool is_initialized(void) +{ + if (likely(landlock_initialized)) + return true; + + pr_warn_once( + "Disabled but requested by user space. " + "You should enable Landlock at boot time: " + "https://docs.kernel.org/userspace-api/landlock.html#boot-time-configuration\n"); + return false; +} + /** * copy_min_struct_from_user - Safe future-proof argument copying * @@ -173,7 +185,7 @@ SYSCALL_DEFINE3(landlock_create_ruleset, /* Build-time checks. */ build_check_abi(); - if (!landlock_initialized) + if (!is_initialized()) return -EOPNOTSUPP; if (flags) { @@ -398,7 +410,7 @@ SYSCALL_DEFINE4(landlock_add_rule, const int, ruleset_fd, struct landlock_ruleset *ruleset; int err; - if (!landlock_initialized) + if (!is_initialized()) return -EOPNOTSUPP; /* No flag for now. */ @@ -458,7 +470,7 @@ SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32, struct landlock_cred_security *new_llcred; int err; - if (!landlock_initialized) + if (!is_initialized()) return -EOPNOTSUPP; /* -- cgit v1.2.3 From 088e2efaf3d25be67f5dbcc26cfe08d7797dff39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= Date: Thu, 7 Mar 2024 10:39:22 +0100 Subject: landlock: Simplify current_check_access_socket() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the handled_access variable in current_check_access_socket() and update access_request instead. One up-to-date variable avoids picking the wrong one. Cc: Konstantin Meskhidze Link: https://lore.kernel.org/r/20240307093923.1466071-1-mic@digikod.net Signed-off-by: Mickaël Salaün --- security/landlock/net.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'security') diff --git a/security/landlock/net.c b/security/landlock/net.c index efa1b644a4af..c8bcd29bde09 100644 --- a/security/landlock/net.c +++ b/security/landlock/net.c @@ -64,12 +64,11 @@ static const struct landlock_ruleset *get_current_net_domain(void) static int current_check_access_socket(struct socket *const sock, struct sockaddr *const address, const int addrlen, - const access_mask_t access_request) + access_mask_t access_request) { __be16 port; layer_mask_t layer_masks[LANDLOCK_NUM_ACCESS_NET] = {}; const struct landlock_rule *rule; - access_mask_t handled_access; struct landlock_id id = { .type = LANDLOCK_KEY_NET_PORT, }; @@ -164,9 +163,9 @@ static int current_check_access_socket(struct socket *const sock, BUILD_BUG_ON(sizeof(port) > sizeof(id.key.data)); rule = landlock_find_rule(dom, id); - handled_access = landlock_init_layer_masks( + access_request = landlock_init_layer_masks( dom, access_request, &layer_masks, LANDLOCK_KEY_NET_PORT); - if (landlock_unmask_layers(rule, handled_access, &layer_masks, + if (landlock_unmask_layers(rule, access_request, &layer_masks, ARRAY_SIZE(layer_masks))) return 0; -- cgit v1.2.3 From e3e37fe022a486d83c71eacb59fb5b6b0ebdbf78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= Date: Thu, 7 Mar 2024 10:39:23 +0100 Subject: landlock: Rename "ptrace" files to "task" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ptrace.[ch] are currently only used for the ptrace LSM hooks but their scope will expand with IPCs and audit support. Rename ptrace.[ch] to task.[ch], which better reflect their content. Similarly, rename landlock_add_ptrace_hooks() to landlock_add_task_hooks(). Keep header files for now. Cc: Günther Noack Cc: Paul Moore Link: https://lore.kernel.org/r/20240307093923.1466071-2-mic@digikod.net Signed-off-by: Mickaël Salaün --- security/landlock/Makefile | 2 +- security/landlock/ptrace.c | 120 --------------------------------------------- security/landlock/ptrace.h | 14 ------ security/landlock/setup.c | 4 +- security/landlock/task.c | 120 +++++++++++++++++++++++++++++++++++++++++++++ security/landlock/task.h | 14 ++++++ 6 files changed, 137 insertions(+), 137 deletions(-) delete mode 100644 security/landlock/ptrace.c delete mode 100644 security/landlock/ptrace.h create mode 100644 security/landlock/task.c create mode 100644 security/landlock/task.h (limited to 'security') diff --git a/security/landlock/Makefile b/security/landlock/Makefile index c2e116f2a299..b4538b7cf7d2 100644 --- a/security/landlock/Makefile +++ b/security/landlock/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_SECURITY_LANDLOCK) := landlock.o landlock-y := setup.o syscalls.o object.o ruleset.o \ - cred.o ptrace.o fs.o + cred.o task.o fs.o landlock-$(CONFIG_INET) += net.o diff --git a/security/landlock/ptrace.c b/security/landlock/ptrace.c deleted file mode 100644 index 2bfc533d36e4..000000000000 --- a/security/landlock/ptrace.c +++ /dev/null @@ -1,120 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Landlock LSM - Ptrace hooks - * - * Copyright © 2017-2020 Mickaël Salaün - * Copyright © 2019-2020 ANSSI - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "cred.h" -#include "ptrace.h" -#include "ruleset.h" -#include "setup.h" - -/** - * domain_scope_le - Checks domain ordering for scoped ptrace - * - * @parent: Parent domain. - * @child: Potential child of @parent. - * - * Checks if the @parent domain is less or equal to (i.e. an ancestor, which - * means a subset of) the @child domain. - */ -static bool domain_scope_le(const struct landlock_ruleset *const parent, - const struct landlock_ruleset *const child) -{ - const struct landlock_hierarchy *walker; - - if (!parent) - return true; - if (!child) - return false; - for (walker = child->hierarchy; walker; walker = walker->parent) { - if (walker == parent->hierarchy) - /* @parent is in the scoped hierarchy of @child. */ - return true; - } - /* There is no relationship between @parent and @child. */ - return false; -} - -static bool task_is_scoped(const struct task_struct *const parent, - const struct task_struct *const child) -{ - bool is_scoped; - const struct landlock_ruleset *dom_parent, *dom_child; - - rcu_read_lock(); - dom_parent = landlock_get_task_domain(parent); - dom_child = landlock_get_task_domain(child); - is_scoped = domain_scope_le(dom_parent, dom_child); - rcu_read_unlock(); - return is_scoped; -} - -static int task_ptrace(const struct task_struct *const parent, - const struct task_struct *const child) -{ - /* Quick return for non-landlocked tasks. */ - if (!landlocked(parent)) - return 0; - if (task_is_scoped(parent, child)) - return 0; - return -EPERM; -} - -/** - * hook_ptrace_access_check - Determines whether the current process may access - * another - * - * @child: Process to be accessed. - * @mode: Mode of attachment. - * - * If the current task has Landlock rules, then the child must have at least - * the same rules. Else denied. - * - * Determines whether a process may access another, returning 0 if permission - * granted, -errno if denied. - */ -static int hook_ptrace_access_check(struct task_struct *const child, - const unsigned int mode) -{ - return task_ptrace(current, child); -} - -/** - * hook_ptrace_traceme - Determines whether another process may trace the - * current one - * - * @parent: Task proposed to be the tracer. - * - * If the parent has Landlock rules, then the current task must have the same - * or more rules. Else denied. - * - * Determines whether the nominated task is permitted to trace the current - * process, returning 0 if permission is granted, -errno if denied. - */ -static int hook_ptrace_traceme(struct task_struct *const parent) -{ - return task_ptrace(parent, current); -} - -static struct security_hook_list landlock_hooks[] __ro_after_init = { - LSM_HOOK_INIT(ptrace_access_check, hook_ptrace_access_check), - LSM_HOOK_INIT(ptrace_traceme, hook_ptrace_traceme), -}; - -__init void landlock_add_ptrace_hooks(void) -{ - security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks), - &landlock_lsmid); -} diff --git a/security/landlock/ptrace.h b/security/landlock/ptrace.h deleted file mode 100644 index 265b220ae3bf..000000000000 --- a/security/landlock/ptrace.h +++ /dev/null @@ -1,14 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Landlock LSM - Ptrace hooks - * - * Copyright © 2017-2019 Mickaël Salaün - * Copyright © 2019 ANSSI - */ - -#ifndef _SECURITY_LANDLOCK_PTRACE_H -#define _SECURITY_LANDLOCK_PTRACE_H - -__init void landlock_add_ptrace_hooks(void); - -#endif /* _SECURITY_LANDLOCK_PTRACE_H */ diff --git a/security/landlock/setup.c b/security/landlock/setup.c index f6dd33143b7f..28519a45b11f 100644 --- a/security/landlock/setup.c +++ b/security/landlock/setup.c @@ -14,8 +14,8 @@ #include "cred.h" #include "fs.h" #include "net.h" -#include "ptrace.h" #include "setup.h" +#include "task.h" bool landlock_initialized __ro_after_init = false; @@ -34,7 +34,7 @@ const struct lsm_id landlock_lsmid = { static int __init landlock_init(void) { landlock_add_cred_hooks(); - landlock_add_ptrace_hooks(); + landlock_add_task_hooks(); landlock_add_fs_hooks(); landlock_add_net_hooks(); landlock_initialized = true; diff --git a/security/landlock/task.c b/security/landlock/task.c new file mode 100644 index 000000000000..849f5123610b --- /dev/null +++ b/security/landlock/task.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Landlock LSM - Ptrace hooks + * + * Copyright © 2017-2020 Mickaël Salaün + * Copyright © 2019-2020 ANSSI + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "cred.h" +#include "ruleset.h" +#include "setup.h" +#include "task.h" + +/** + * domain_scope_le - Checks domain ordering for scoped ptrace + * + * @parent: Parent domain. + * @child: Potential child of @parent. + * + * Checks if the @parent domain is less or equal to (i.e. an ancestor, which + * means a subset of) the @child domain. + */ +static bool domain_scope_le(const struct landlock_ruleset *const parent, + const struct landlock_ruleset *const child) +{ + const struct landlock_hierarchy *walker; + + if (!parent) + return true; + if (!child) + return false; + for (walker = child->hierarchy; walker; walker = walker->parent) { + if (walker == parent->hierarchy) + /* @parent is in the scoped hierarchy of @child. */ + return true; + } + /* There is no relationship between @parent and @child. */ + return false; +} + +static bool task_is_scoped(const struct task_struct *const parent, + const struct task_struct *const child) +{ + bool is_scoped; + const struct landlock_ruleset *dom_parent, *dom_child; + + rcu_read_lock(); + dom_parent = landlock_get_task_domain(parent); + dom_child = landlock_get_task_domain(child); + is_scoped = domain_scope_le(dom_parent, dom_child); + rcu_read_unlock(); + return is_scoped; +} + +static int task_ptrace(const struct task_struct *const parent, + const struct task_struct *const child) +{ + /* Quick return for non-landlocked tasks. */ + if (!landlocked(parent)) + return 0; + if (task_is_scoped(parent, child)) + return 0; + return -EPERM; +} + +/** + * hook_ptrace_access_check - Determines whether the current process may access + * another + * + * @child: Process to be accessed. + * @mode: Mode of attachment. + * + * If the current task has Landlock rules, then the child must have at least + * the same rules. Else denied. + * + * Determines whether a process may access another, returning 0 if permission + * granted, -errno if denied. + */ +static int hook_ptrace_access_check(struct task_struct *const child, + const unsigned int mode) +{ + return task_ptrace(current, child); +} + +/** + * hook_ptrace_traceme - Determines whether another process may trace the + * current one + * + * @parent: Task proposed to be the tracer. + * + * If the parent has Landlock rules, then the current task must have the same + * or more rules. Else denied. + * + * Determines whether the nominated task is permitted to trace the current + * process, returning 0 if permission is granted, -errno if denied. + */ +static int hook_ptrace_traceme(struct task_struct *const parent) +{ + return task_ptrace(parent, current); +} + +static struct security_hook_list landlock_hooks[] __ro_after_init = { + LSM_HOOK_INIT(ptrace_access_check, hook_ptrace_access_check), + LSM_HOOK_INIT(ptrace_traceme, hook_ptrace_traceme), +}; + +__init void landlock_add_task_hooks(void) +{ + security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks), + &landlock_lsmid); +} diff --git a/security/landlock/task.h b/security/landlock/task.h new file mode 100644 index 000000000000..7c00360219a2 --- /dev/null +++ b/security/landlock/task.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Landlock LSM - Ptrace hooks + * + * Copyright © 2017-2019 Mickaël Salaün + * Copyright © 2019 ANSSI + */ + +#ifndef _SECURITY_LANDLOCK_TASK_H +#define _SECURITY_LANDLOCK_TASK_H + +__init void landlock_add_task_hooks(void); + +#endif /* _SECURITY_LANDLOCK_TASK_H */ -- cgit v1.2.3 From 63817febd1f3c27f633b2bce0d6db328e59fd019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= Date: Thu, 7 Mar 2024 10:52:03 +0100 Subject: landlock: Use f_cred in security_file_open() hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use landlock_cred(file->f_cred)->domain instead of landlock_get_current_domain() in security_file_open() hook implementation. This should not change the current behavior but could avoid potential race conditions in case of current task's credentials change. This will also ensure consistency with upcoming audit support relying on file->f_cred. Add and use a new get_fs_domain() helper to mask non-filesystem domains. file->f_cred is set by path_openat()/alloc_empty_file()/init_file() just before calling security_file_alloc(). Cc: Christian Brauner Cc: Günther Noack Cc: Jann Horn Cc: Paul Moore Reviewed-by: Kees Cook Link: https://lore.kernel.org/r/20240307095203.1467189-1-mic@digikod.net Signed-off-by: Mickaël Salaün --- security/landlock/fs.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'security') diff --git a/security/landlock/fs.c b/security/landlock/fs.c index 6f0bf1434a2c..c15559432d3d 100644 --- a/security/landlock/fs.c +++ b/security/landlock/fs.c @@ -248,15 +248,18 @@ get_handled_fs_accesses(const struct landlock_ruleset *const domain) LANDLOCK_ACCESS_FS_INITIALLY_DENIED; } -static const struct landlock_ruleset *get_current_fs_domain(void) +static const struct landlock_ruleset * +get_fs_domain(const struct landlock_ruleset *const domain) { - const struct landlock_ruleset *const dom = - landlock_get_current_domain(); - - if (!dom || !get_raw_handled_fs_accesses(dom)) + if (!domain || !get_raw_handled_fs_accesses(domain)) return NULL; - return dom; + return domain; +} + +static const struct landlock_ruleset *get_current_fs_domain(void) +{ + return get_fs_domain(landlock_get_current_domain()); } /* @@ -1334,7 +1337,8 @@ static int hook_file_open(struct file *const file) layer_mask_t layer_masks[LANDLOCK_NUM_ACCESS_FS] = {}; access_mask_t open_access_request, full_access_request, allowed_access; const access_mask_t optional_access = LANDLOCK_ACCESS_FS_TRUNCATE; - const struct landlock_ruleset *const dom = get_current_fs_domain(); + const struct landlock_ruleset *const dom = + get_fs_domain(landlock_cred(file->f_cred)->domain); if (!dom) return 0; -- cgit v1.2.3 From a5a858f622a0aff5cdb5e271442cd01b2a01467f Mon Sep 17 00:00:00 2001 From: Casey Schaufler Date: Thu, 14 Mar 2024 11:31:26 -0400 Subject: lsm: use 32-bit compatible data types in LSM syscalls Change the size parameters in lsm_list_modules(), lsm_set_self_attr() and lsm_get_self_attr() from size_t to u32. This avoids the need to have different interfaces for 32 and 64 bit systems. Cc: stable@vger.kernel.org Fixes: a04a1198088a ("LSM: syscalls for current process attributes") Fixes: ad4aff9ec25f ("LSM: Create lsm_list_modules system call") Signed-off-by: Casey Schaufler Reported-and-reviewed-by: Dmitry V. Levin [PM: subject and metadata tweaks, syscall.h fixes] Signed-off-by: Paul Moore --- security/apparmor/lsm.c | 4 ++-- security/lsm_syscalls.c | 10 +++++----- security/security.c | 12 ++++++------ security/selinux/hooks.c | 4 ++-- security/smack/smack_lsm.c | 4 ++-- 5 files changed, 17 insertions(+), 17 deletions(-) (limited to 'security') diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 9a3dcaafb5b1..cef8c466af80 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -779,7 +779,7 @@ static int apparmor_sb_pivotroot(const struct path *old_path, } static int apparmor_getselfattr(unsigned int attr, struct lsm_ctx __user *lx, - size_t *size, u32 flags) + u32 *size, u32 flags) { int error = -ENOENT; struct aa_task_ctx *ctx = task_ctx(current); @@ -924,7 +924,7 @@ fail: } static int apparmor_setselfattr(unsigned int attr, struct lsm_ctx *ctx, - size_t size, u32 flags) + u32 size, u32 flags) { int rc; diff --git a/security/lsm_syscalls.c b/security/lsm_syscalls.c index 5d391b1f7e69..8440948a690c 100644 --- a/security/lsm_syscalls.c +++ b/security/lsm_syscalls.c @@ -53,7 +53,7 @@ u64 lsm_name_to_attr(const char *name) * value indicating the reason for the error is returned. */ SYSCALL_DEFINE4(lsm_set_self_attr, unsigned int, attr, struct lsm_ctx __user *, - ctx, size_t, size, u32, flags) + ctx, u32, size, u32, flags) { return security_setselfattr(attr, ctx, size, flags); } @@ -75,7 +75,7 @@ SYSCALL_DEFINE4(lsm_set_self_attr, unsigned int, attr, struct lsm_ctx __user *, * a negative value indicating the error is returned. */ SYSCALL_DEFINE4(lsm_get_self_attr, unsigned int, attr, struct lsm_ctx __user *, - ctx, size_t __user *, size, u32, flags) + ctx, u32 __user *, size, u32, flags) { return security_getselfattr(attr, ctx, size, flags); } @@ -93,11 +93,11 @@ SYSCALL_DEFINE4(lsm_get_self_attr, unsigned int, attr, struct lsm_ctx __user *, * required size. In all other cases a negative value indicating the * error is returned. */ -SYSCALL_DEFINE3(lsm_list_modules, u64 __user *, ids, size_t __user *, size, +SYSCALL_DEFINE3(lsm_list_modules, u64 __user *, ids, u32 __user *, size, u32, flags) { - size_t total_size = lsm_active_cnt * sizeof(*ids); - size_t usize; + u32 total_size = lsm_active_cnt * sizeof(*ids); + u32 usize; int i; if (flags) diff --git a/security/security.c b/security/security.c index a07f43c58d65..5b2e0a15377d 100644 --- a/security/security.c +++ b/security/security.c @@ -785,7 +785,7 @@ static int lsm_superblock_alloc(struct super_block *sb) * Returns 0 on success, -E2BIG if userspace buffer is not large enough, * -EFAULT on a copyout error, -ENOMEM if memory can't be allocated. */ -int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, size_t *uctx_len, +int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, u32 *uctx_len, void *val, size_t val_len, u64 id, u64 flags) { @@ -3931,14 +3931,14 @@ EXPORT_SYMBOL(security_d_instantiate); * If @size is insufficient to contain the data -E2BIG is returned. */ int security_getselfattr(unsigned int attr, struct lsm_ctx __user *uctx, - size_t __user *size, u32 flags) + u32 __user *size, u32 flags) { struct security_hook_list *hp; struct lsm_ctx lctx = { .id = LSM_ID_UNDEF, }; u8 __user *base = (u8 __user *)uctx; - size_t total = 0; - size_t entrysize; - size_t left; + u32 entrysize; + u32 total = 0; + u32 left; bool toobig = false; bool single = false; int count = 0; @@ -4024,7 +4024,7 @@ int security_getselfattr(unsigned int attr, struct lsm_ctx __user *uctx, * LSM specific failure. */ int security_setselfattr(unsigned int attr, struct lsm_ctx __user *uctx, - size_t size, u32 flags) + u32 size, u32 flags) { struct security_hook_list *hp; struct lsm_ctx *lctx; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8db4875164ab..3448454c82d0 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6559,7 +6559,7 @@ abort_change: * There will only ever be one attribute. */ static int selinux_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx, - size_t *size, u32 flags) + u32 *size, u32 flags) { int rc; char *val = NULL; @@ -6574,7 +6574,7 @@ static int selinux_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx, } static int selinux_setselfattr(unsigned int attr, struct lsm_ctx *ctx, - size_t size, u32 flags) + u32 size, u32 flags) { int rc; diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 28be26712396..146667937811 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -3653,7 +3653,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) * There will only ever be one attribute. */ static int smack_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx, - size_t *size, u32 flags) + u32 *size, u32 flags) { int rc; struct smack_known *skp; @@ -3774,7 +3774,7 @@ static int do_setattr(u64 attr, void *value, size_t size) * Returns 0 on success, an error code otherwise. */ static int smack_setselfattr(unsigned int attr, struct lsm_ctx *ctx, - size_t size, u32 flags) + u32 size, u32 flags) { int rc; -- cgit v1.2.3 From eaf0e7a3d2711018789e9fdb89191d19aa139c47 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 13 Mar 2024 21:37:48 -0400 Subject: lsm: handle the NULL buffer case in lsm_fill_user_ctx() Passing a NULL buffer into the lsm_get_self_attr() syscall is a valid way to quickly determine the minimum size of the buffer needed to for the syscall to return all of the LSM attributes to the caller. Unfortunately we/I broke that behavior in commit d7cf3412a9f6 ("lsm: consolidate buffer size handling into lsm_fill_user_ctx()") such that it returned an error to the caller; this patch restores the original desired behavior of using the NULL buffer as a quick way to correctly size the attribute buffer. Cc: stable@vger.kernel.org Fixes: d7cf3412a9f6 ("lsm: consolidate buffer size handling into lsm_fill_user_ctx()") Signed-off-by: Paul Moore --- security/security.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'security') diff --git a/security/security.c b/security/security.c index 5b2e0a15377d..7e118858b545 100644 --- a/security/security.c +++ b/security/security.c @@ -780,7 +780,9 @@ static int lsm_superblock_alloc(struct super_block *sb) * @id: LSM id * @flags: LSM defined flags * - * Fill all of the fields in a userspace lsm_ctx structure. + * Fill all of the fields in a userspace lsm_ctx structure. If @uctx is NULL + * simply calculate the required size to output via @utc_len and return + * success. * * Returns 0 on success, -E2BIG if userspace buffer is not large enough, * -EFAULT on a copyout error, -ENOMEM if memory can't be allocated. @@ -799,6 +801,10 @@ int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, u32 *uctx_len, goto out; } + /* no buffer - return success/0 and set @uctx_len to the req size */ + if (!uctx) + goto out; + nctx = kzalloc(nctx_len, GFP_KERNEL); if (nctx == NULL) { rc = -ENOMEM; -- cgit v1.2.3