* [PATCH 0/6] file capabilities cleanups: introduction @ 2008-09-27 2:27 Serge E. Hallyn 2008-09-27 2:27 ` [PATCH 1/6] file capabilities: add no_file_caps switch (v3) Serge E. Hallyn 0 siblings, 1 reply; 17+ messages in thread From: Serge E. Hallyn @ 2008-09-27 2:27 UTC (permalink / raw) To: linux-kernel; +Cc: linux-security-module Following is a set of file capabilities cleanups. The first two patches are a repost of my previous patches which introduce a no_file_caps boot option, and remove the CONFIG_SECURITY_FILE_CAPABILITIES config option. The rest of the patches both clean up some of the capabilities code and reduce the kernel size (since enabling file capabilities grew it). Andrew Morgan, if you have a moment, please do take a close look and make sure I'm not doing anything stupid/wrong in the cleanups! However ltp shows no difference with and without the patchset. Following are the kernel sizes after some of the patches. original, pre-patch, with file capabilities compiled out: text data bss dec hex filename 4188468 234432 316472 4739372 48512c vmlinux original, pre-patch, with file capabilities compiled in: 4189356 234432 316472 4740260 4854a4 vmlinux plain with fcaps always-on: 4189392 234456 316472 4740320 4854e0 vmlinux with non-inline cap_safe_nice: 4189112 234456 316472 4740040 4853c8 vmlinux with cleaned-up setcap: 4189120 234456 316472 4740048 4853d0 vmlinux with needless check for target!=current removed from cap_capset: 4189104 234456 316472 4740032 4853c0 vmlinux with needless(?) bprm_clear_caps calls removed: 4189088 234456 316472 4740016 4853b0 vmlinux thanks, -serge ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 1/6] file capabilities: add no_file_caps switch (v3) 2008-09-27 2:27 [PATCH 0/6] file capabilities cleanups: introduction Serge E. Hallyn @ 2008-09-27 2:27 ` Serge E. Hallyn 2008-09-27 2:27 ` [PATCH 2/6] file capabilities: remove CONFIG_SECURITY_FILE_CAPABILITIES Serge E. Hallyn ` (4 more replies) 0 siblings, 5 replies; 17+ messages in thread From: Serge E. Hallyn @ 2008-09-27 2:27 UTC (permalink / raw) To: linux-kernel; +Cc: linux-security-module, Serge Hallyn From: Serge Hallyn <serue@us.ibm.com> Add a no_file_caps boot option when file capabilities are compiled into the kernel (CONFIG_SECURITY_FILE_CAPABILITIES=y). This allows distributions to ship a kernel with file capabilities compiled in, without forcing users to use (and understand and trust) them. When no_file_caps is specified at boot, then when a process executes a file, any file capabilities stored with that file will not be used in the calculation of the process' new capability sets. This means that booting with the no_file_caps boot option will not be the same as booting a kernel with file capabilities compiled out - in particular a task with CAP_SETPCAP will not have any chance of passing capabilities to another task (which isn't "really" possible anyway, and which may soon by killed altogether by David Howells in any case), and it will instead be able to put new capabilities in its pI. However since fI will always be empty and pI is masked with fI, it gains the task nothing. We also support the extra prctl options, setting securebits and dropping capabilities from the per-process bounding set. The other remaining difference is that killpriv, task_setscheduler, setioprio, and setnice will continue to be hooked. That will be noticable in the case where a root task changed its uid while keeping some caps, and another task owned by the new uid tries to change settings for the more privileged task. Changelog: Sep 23 2008: nixed file_caps_enabled when file caps are not compiled in as it isn't used. Document no_file_caps in kernel-parameters.txt. Signed-off-by: Serge Hallyn <serue@us.ibm.com> Acked-by: Andrew G. Morgan <morgan@kernel.org> --- Documentation/kernel-parameters.txt | 4 ++++ include/linux/capability.h | 3 +++ kernel/capability.c | 11 +++++++++++ security/commoncap.c | 5 +++++ 4 files changed, 23 insertions(+), 0 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 1150444..cbb04bf 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1393,6 +1393,10 @@ and is between 256 and 4096 characters. It is defined in the file instruction doesn't work correctly and not to use it. + no_file_caps Tells the kernel not to honor file capabilities. The + only way then for a file to be executed with privilege + is to be setuid root or executed by root. + nohalt [IA-64] Tells the kernel not to use the power saving function PAL_HALT_LIGHT when idle. This increases power-consumption. On the positive side, it reduces diff --git a/include/linux/capability.h b/include/linux/capability.h index 9d1fe30..5bc145b 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -68,6 +68,9 @@ typedef struct __user_cap_data_struct { #define VFS_CAP_U32 VFS_CAP_U32_2 #define VFS_CAP_REVISION VFS_CAP_REVISION_2 +#ifdef CONFIG_SECURITY_FILE_CAPABILITIES +extern int file_caps_enabled; +#endif struct vfs_cap_data { __le32 magic_etc; /* Little endian */ diff --git a/kernel/capability.c b/kernel/capability.c index 33e51e7..e13a685 100644 --- a/kernel/capability.c +++ b/kernel/capability.c @@ -33,6 +33,17 @@ EXPORT_SYMBOL(__cap_empty_set); EXPORT_SYMBOL(__cap_full_set); EXPORT_SYMBOL(__cap_init_eff_set); +#ifdef CONFIG_SECURITY_FILE_CAPABILITIES +int file_caps_enabled = 1; + +static int __init file_caps_disable(char *str) +{ + file_caps_enabled = 0; + return 1; +} +__setup("no_file_caps", file_caps_disable); +#endif + /* * More recent versions of libcap are available from: * diff --git a/security/commoncap.c b/security/commoncap.c index e4c4b3f..5f1fec0 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -279,6 +279,11 @@ static int get_file_caps(struct linux_binprm *bprm) struct vfs_cap_data vcaps; struct inode *inode; + if (!file_caps_enabled) { + bprm_clear_caps(bprm); + return 0; + } + if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) { bprm_clear_caps(bprm); return 0; -- 1.5.1.1.GIT ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 2/6] file capabilities: remove CONFIG_SECURITY_FILE_CAPABILITIES 2008-09-27 2:27 ` [PATCH 1/6] file capabilities: add no_file_caps switch (v3) Serge E. Hallyn @ 2008-09-27 2:27 ` Serge E. Hallyn 2008-09-27 4:25 ` Andrew G. Morgan 2008-09-27 2:27 ` [PATCH 3/6] file capabilities: uninline cap_safe_nice Serge E. Hallyn ` (3 subsequent siblings) 4 siblings, 1 reply; 17+ messages in thread From: Serge E. Hallyn @ 2008-09-27 2:27 UTC (permalink / raw) To: linux-kernel; +Cc: linux-security-module, Serge Hallyn From: Serge Hallyn <serue@us.ibm.com> Remove the option to compile the kernel without file capabilities. Not compiling file capabilities actually makes the kernel less safe, as it includes the possibility for a task changing another task's capabilities. Some are concerned that userspace tools (and user education) are not up to the task of properly configuring file capabilities on a system. For those cases, there is now the ability to boot with the no_file_caps boot option. This will prevent file capabilities from being used in the capabilities recalculation at exec, but will not change the rest of the kernel behavior which used to be switchable using the CONFIG_SECURITY_FILE_CAPABILITIES option. Signed-off-by: Serge Hallyn <serue@us.ibm.com> --- fs/open.c | 8 -- include/linux/capability.h | 2 - include/linux/init_task.h | 4 - kernel/capability.c | 158 -------------------------------------------- security/Kconfig | 9 --- security/commoncap.c | 53 --------------- 6 files changed, 0 insertions(+), 234 deletions(-) diff --git a/fs/open.c b/fs/open.c index 07da935..6e1cd6e 100644 --- a/fs/open.c +++ b/fs/open.c @@ -444,14 +444,6 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) /* * Clear the capabilities if we switch to a non-root user */ -#ifndef CONFIG_SECURITY_FILE_CAPABILITIES - /* - * FIXME: There is a race here against sys_capset. The - * capabilities can change yet we will restore the old - * value below. We should hold task_capabilities_lock, - * but we cannot because user_path_at can sleep. - */ -#endif /* ndef CONFIG_SECURITY_FILE_CAPABILITIES */ if (current->uid) old_cap = cap_set_effective(__cap_empty_set); else diff --git a/include/linux/capability.h b/include/linux/capability.h index 5bc145b..07a9ada 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -68,9 +68,7 @@ typedef struct __user_cap_data_struct { #define VFS_CAP_U32 VFS_CAP_U32_2 #define VFS_CAP_REVISION VFS_CAP_REVISION_2 -#ifdef CONFIG_SECURITY_FILE_CAPABILITIES extern int file_caps_enabled; -#endif struct vfs_cap_data { __le32 magic_etc; /* Little endian */ diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 021d8e7..7c177b9 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -102,16 +102,12 @@ extern struct group_info init_groups; #define INIT_IDS #endif -#ifdef CONFIG_SECURITY_FILE_CAPABILITIES /* * Because of the reduced scope of CAP_SETPCAP when filesystem * capabilities are in effect, it is safe to allow CAP_SETPCAP to * be available in the default configuration. */ # define CAP_INIT_BSET CAP_FULL_SET -#else -# define CAP_INIT_BSET CAP_INIT_EFF_SET -#endif /* * INIT_TASK is used to set up the first task table, touch at diff --git a/kernel/capability.c b/kernel/capability.c index e13a685..d39c989 100644 --- a/kernel/capability.c +++ b/kernel/capability.c @@ -33,7 +33,6 @@ EXPORT_SYMBOL(__cap_empty_set); EXPORT_SYMBOL(__cap_full_set); EXPORT_SYMBOL(__cap_init_eff_set); -#ifdef CONFIG_SECURITY_FILE_CAPABILITIES int file_caps_enabled = 1; static int __init file_caps_disable(char *str) @@ -42,7 +41,6 @@ static int __init file_caps_disable(char *str) return 1; } __setup("no_file_caps", file_caps_disable); -#endif /* * More recent versions of libcap are available from: @@ -126,160 +124,6 @@ static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy) return 0; } -#ifndef CONFIG_SECURITY_FILE_CAPABILITIES - -/* - * Without filesystem capability support, we nominally support one process - * setting the capabilities of another - */ -static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp, - kernel_cap_t *pIp, kernel_cap_t *pPp) -{ - struct task_struct *target; - int ret; - - spin_lock(&task_capability_lock); - read_lock(&tasklist_lock); - - if (pid && pid != task_pid_vnr(current)) { - target = find_task_by_vpid(pid); - if (!target) { - ret = -ESRCH; - goto out; - } - } else - target = current; - - ret = security_capget(target, pEp, pIp, pPp); - -out: - read_unlock(&tasklist_lock); - spin_unlock(&task_capability_lock); - - return ret; -} - -/* - * cap_set_pg - set capabilities for all processes in a given process - * group. We call this holding task_capability_lock and tasklist_lock. - */ -static inline int cap_set_pg(int pgrp_nr, kernel_cap_t *effective, - kernel_cap_t *inheritable, - kernel_cap_t *permitted) -{ - struct task_struct *g, *target; - int ret = -EPERM; - int found = 0; - struct pid *pgrp; - - spin_lock(&task_capability_lock); - read_lock(&tasklist_lock); - - pgrp = find_vpid(pgrp_nr); - do_each_pid_task(pgrp, PIDTYPE_PGID, g) { - target = g; - while_each_thread(g, target) { - if (!security_capset_check(target, effective, - inheritable, permitted)) { - security_capset_set(target, effective, - inheritable, permitted); - ret = 0; - } - found = 1; - } - } while_each_pid_task(pgrp, PIDTYPE_PGID, g); - - read_unlock(&tasklist_lock); - spin_unlock(&task_capability_lock); - - if (!found) - ret = 0; - return ret; -} - -/* - * cap_set_all - set capabilities for all processes other than init - * and self. We call this holding task_capability_lock and tasklist_lock. - */ -static inline int cap_set_all(kernel_cap_t *effective, - kernel_cap_t *inheritable, - kernel_cap_t *permitted) -{ - struct task_struct *g, *target; - int ret = -EPERM; - int found = 0; - - spin_lock(&task_capability_lock); - read_lock(&tasklist_lock); - - do_each_thread(g, target) { - if (target == current - || is_container_init(target->group_leader)) - continue; - found = 1; - if (security_capset_check(target, effective, inheritable, - permitted)) - continue; - ret = 0; - security_capset_set(target, effective, inheritable, permitted); - } while_each_thread(g, target); - - read_unlock(&tasklist_lock); - spin_unlock(&task_capability_lock); - - if (!found) - ret = 0; - - return ret; -} - -/* - * Given the target pid does not refer to the current process we - * need more elaborate support... (This support is not present when - * filesystem capabilities are configured.) - */ -static inline int do_sys_capset_other_tasks(pid_t pid, kernel_cap_t *effective, - kernel_cap_t *inheritable, - kernel_cap_t *permitted) -{ - struct task_struct *target; - int ret; - - if (!capable(CAP_SETPCAP)) - return -EPERM; - - if (pid == -1) /* all procs other than current and init */ - return cap_set_all(effective, inheritable, permitted); - - else if (pid < 0) /* all procs in process group */ - return cap_set_pg(-pid, effective, inheritable, permitted); - - /* target != current */ - spin_lock(&task_capability_lock); - read_lock(&tasklist_lock); - - target = find_task_by_vpid(pid); - if (!target) - ret = -ESRCH; - else { - ret = security_capset_check(target, effective, inheritable, - permitted); - - /* having verified that the proposed changes are legal, - we now put them into effect. */ - if (!ret) - security_capset_set(target, effective, inheritable, - permitted); - } - - read_unlock(&tasklist_lock); - spin_unlock(&task_capability_lock); - - return ret; -} - -#else /* ie., def CONFIG_SECURITY_FILE_CAPABILITIES */ - /* * If we have configured with filesystem capability support, then the * only thing that can change the capabilities of the current process @@ -327,8 +171,6 @@ static inline int do_sys_capset_other_tasks(pid_t pid, return -EPERM; } -#endif /* ie., ndef CONFIG_SECURITY_FILE_CAPABILITIES */ - /* * Atomically modify the effective capabilities returning the original * value. No permission check is performed here - it is assumed that the diff --git a/security/Kconfig b/security/Kconfig index 5592939..2cf7fb9 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -73,15 +73,6 @@ config SECURITY_NETWORK_XFRM IPSec. If you are unsure how to answer this question, answer N. -config SECURITY_FILE_CAPABILITIES - bool "File POSIX Capabilities" - default n - help - This enables filesystem capabilities, allowing you to give - binaries a subset of root's powers without using setuid 0. - - If in doubt, answer N. - config SECURITY_ROOTPLUG bool "Root Plug Support" depends on USB=y && SECURITY diff --git a/security/commoncap.c b/security/commoncap.c index 5f1fec0..9bfef94 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -93,8 +93,6 @@ int cap_capget (struct task_struct *target, kernel_cap_t *effective, return 0; } -#ifdef CONFIG_SECURITY_FILE_CAPABILITIES - static inline int cap_block_setpcap(struct task_struct *target) { /* @@ -116,17 +114,6 @@ static inline int cap_inh_is_capped(void) static inline int cap_limit_ptraced_target(void) { return 1; } -#else /* ie., ndef CONFIG_SECURITY_FILE_CAPABILITIES */ - -static inline int cap_block_setpcap(struct task_struct *t) { return 0; } -static inline int cap_inh_is_capped(void) { return 1; } -static inline int cap_limit_ptraced_target(void) -{ - return !capable(CAP_SETPCAP); -} - -#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */ - int cap_capset_check (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted) { @@ -176,8 +163,6 @@ static inline void bprm_clear_caps(struct linux_binprm *bprm) bprm->cap_effective = false; } -#ifdef CONFIG_SECURITY_FILE_CAPABILITIES - int cap_inode_need_killpriv(struct dentry *dentry) { struct inode *inode = dentry->d_inode; @@ -317,24 +302,6 @@ out: return rc; } -#else -int cap_inode_need_killpriv(struct dentry *dentry) -{ - return 0; -} - -int cap_inode_killpriv(struct dentry *dentry) -{ - return 0; -} - -static inline int get_file_caps(struct linux_binprm *bprm) -{ - bprm_clear_caps(bprm); - return 0; -} -#endif - int cap_bprm_set_security (struct linux_binprm *bprm) { int ret; @@ -535,7 +502,6 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, return 0; } -#ifdef CONFIG_SECURITY_FILE_CAPABILITIES /* * Rationale: code calling task_setscheduler, task_setioprio, and * task_setnice, assumes that @@ -587,22 +553,6 @@ static long cap_prctl_drop(unsigned long cap) return 0; } -#else -int cap_task_setscheduler (struct task_struct *p, int policy, - struct sched_param *lp) -{ - return 0; -} -int cap_task_setioprio (struct task_struct *p, int ioprio) -{ - return 0; -} -int cap_task_setnice (struct task_struct *p, int nice) -{ - return 0; -} -#endif - int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, long *rc_p) { @@ -615,7 +565,6 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, else error = !!cap_raised(current->cap_bset, arg2); break; -#ifdef CONFIG_SECURITY_FILE_CAPABILITIES case PR_CAPBSET_DROP: error = cap_prctl_drop(arg2); break; @@ -662,8 +611,6 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, error = current->securebits; break; -#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */ - case PR_GET_KEEPCAPS: if (issecure(SECURE_KEEP_CAPS)) error = 1; -- 1.5.1.1.GIT ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH 2/6] file capabilities: remove CONFIG_SECURITY_FILE_CAPABILITIES 2008-09-27 2:27 ` [PATCH 2/6] file capabilities: remove CONFIG_SECURITY_FILE_CAPABILITIES Serge E. Hallyn @ 2008-09-27 4:25 ` Andrew G. Morgan 0 siblings, 0 replies; 17+ messages in thread From: Andrew G. Morgan @ 2008-09-27 4:25 UTC (permalink / raw) To: Serge E. Hallyn; +Cc: linux-kernel, linux-security-module -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Serge E. Hallyn wrote: > From: Serge Hallyn <serue@us.ibm.com> > > Remove the option to compile the kernel without file capabilities. Not > compiling file capabilities actually makes the kernel less safe, as it > includes the possibility for a task changing another task's capabilities. > > Some are concerned that userspace tools (and user education) are not > up to the task of properly configuring file capabilities on a system. > For those cases, there is now the ability to boot with the no_file_caps > boot option. This will prevent file capabilities from being used in > the capabilities recalculation at exec, but will not change the rest > of the kernel behavior which used to be switchable using the > CONFIG_SECURITY_FILE_CAPABILITIES option. > > Signed-off-by: Serge Hallyn <serue@us.ibm.com> Acked-by: Andrew G. Morgan <morgan@kernel.org> > --- > fs/open.c | 8 -- > include/linux/capability.h | 2 - > include/linux/init_task.h | 4 - > kernel/capability.c | 158 -------------------------------------------- > security/Kconfig | 9 --- > security/commoncap.c | 53 --------------- > 6 files changed, 0 insertions(+), 234 deletions(-) > > diff --git a/fs/open.c b/fs/open.c > index 07da935..6e1cd6e 100644 [...snip...] Cheers Andrew -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (Darwin) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFI3bW9+bHCR3gb8jsRAoD6AKCdF8HNGdT8MPqWUBqrf8+BXGEyZwCfZc2T +/hD1+FB2fTLae+vEbKpWX0= =NerD -----END PGP SIGNATURE----- ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 3/6] file capabilities: uninline cap_safe_nice 2008-09-27 2:27 ` [PATCH 1/6] file capabilities: add no_file_caps switch (v3) Serge E. Hallyn 2008-09-27 2:27 ` [PATCH 2/6] file capabilities: remove CONFIG_SECURITY_FILE_CAPABILITIES Serge E. Hallyn @ 2008-09-27 2:27 ` Serge E. Hallyn 2008-09-27 4:26 ` Andrew G. Morgan 2008-09-27 2:27 ` [PATCH 4/6] file capabilities: clean up setcap code Serge E. Hallyn ` (2 subsequent siblings) 4 siblings, 1 reply; 17+ messages in thread From: Serge E. Hallyn @ 2008-09-27 2:27 UTC (permalink / raw) To: linux-kernel; +Cc: linux-security-module, Serge E. Hallyn This reduces the kernel size by 289 bytes. Signed-off-by: Serge E. Hallyn <serue@us.ibm.com> --- security/commoncap.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/security/commoncap.c b/security/commoncap.c index 9bfef94..d48fdd8 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -512,7 +512,7 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, * yet with increased caps. * So we check for increased caps on the target process. */ -static inline int cap_safe_nice(struct task_struct *p) +static int cap_safe_nice(struct task_struct *p) { if (!cap_issubset(p->cap_permitted, current->cap_permitted) && !capable(CAP_SYS_NICE)) -- 1.5.1.1.GIT ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH 3/6] file capabilities: uninline cap_safe_nice 2008-09-27 2:27 ` [PATCH 3/6] file capabilities: uninline cap_safe_nice Serge E. Hallyn @ 2008-09-27 4:26 ` Andrew G. Morgan 2008-09-27 5:27 ` James Morris 0 siblings, 1 reply; 17+ messages in thread From: Andrew G. Morgan @ 2008-09-27 4:26 UTC (permalink / raw) To: Serge E. Hallyn; +Cc: linux-kernel, linux-security-module -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Serge E. Hallyn wrote: > This reduces the kernel size by 289 bytes. > > Signed-off-by: Serge E. Hallyn <serue@us.ibm.com> Acked-by: Andrew G. Morgan <morgan@kernel.org> Cheers Andrew > --- > security/commoncap.c | 2 +- > 1 files changed, 1 insertions(+), 1 deletions(-) > > diff --git a/security/commoncap.c b/security/commoncap.c > index 9bfef94..d48fdd8 100644 > --- a/security/commoncap.c > +++ b/security/commoncap.c > @@ -512,7 +512,7 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, > * yet with increased caps. > * So we check for increased caps on the target process. > */ > -static inline int cap_safe_nice(struct task_struct *p) > +static int cap_safe_nice(struct task_struct *p) > { > if (!cap_issubset(p->cap_permitted, current->cap_permitted) && > !capable(CAP_SYS_NICE)) -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (Darwin) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFI3bX0+bHCR3gb8jsRApVqAKCuFmvJTlIiAYxXW5W3JNncFYmmrQCfa95h Ik/MLVnpPtZdmuInkJSOof4= =3aYe -----END PGP SIGNATURE----- ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/6] file capabilities: uninline cap_safe_nice 2008-09-27 4:26 ` Andrew G. Morgan @ 2008-09-27 5:27 ` James Morris 0 siblings, 0 replies; 17+ messages in thread From: James Morris @ 2008-09-27 5:27 UTC (permalink / raw) To: Andrew G. Morgan; +Cc: Serge E. Hallyn, linux-kernel, linux-security-module On Fri, 26 Sep 2008, Andrew G. Morgan wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > > > Serge E. Hallyn wrote: > > This reduces the kernel size by 289 bytes. > > > > Signed-off-by: Serge E. Hallyn <serue@us.ibm.com> > > Acked-by: Andrew G. Morgan <morgan@kernel.org> > This one makes sense on its own, applied to: git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6#next - James -- James Morris <jmorris@namei.org> ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 4/6] file capabilities: clean up setcap code 2008-09-27 2:27 ` [PATCH 1/6] file capabilities: add no_file_caps switch (v3) Serge E. Hallyn 2008-09-27 2:27 ` [PATCH 2/6] file capabilities: remove CONFIG_SECURITY_FILE_CAPABILITIES Serge E. Hallyn 2008-09-27 2:27 ` [PATCH 3/6] file capabilities: uninline cap_safe_nice Serge E. Hallyn @ 2008-09-27 2:27 ` Serge E. Hallyn 2008-09-27 4:58 ` Andrew G. Morgan 2008-09-27 2:27 ` [PATCH 5/6] file capabilities: remove needless inline functions Serge E. Hallyn 2008-09-27 2:27 ` [PATCH 6/6] file capabilities: remove needless (?) bprm_clear_caps calls Serge E. Hallyn 4 siblings, 1 reply; 17+ messages in thread From: Serge E. Hallyn @ 2008-09-27 2:27 UTC (permalink / raw) To: linux-kernel; +Cc: linux-security-module, Serge E. Hallyn Clean up the sys_capset codepath a bit to account for the fact that you can now not ever, never, capset on another task. Signed-off-by: Serge E. Hallyn <serue@us.ibm.com> --- kernel/capability.c | 83 +++++++++++++++++++------------------------------- 1 files changed, 32 insertions(+), 51 deletions(-) diff --git a/kernel/capability.c b/kernel/capability.c index d39c989..92dd85b 100644 --- a/kernel/capability.c +++ b/kernel/capability.c @@ -132,46 +132,31 @@ static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy) * process. The net result is that we can limit our use of locks to * when we are reading the caps of another process. */ -static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp, +static int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp, kernel_cap_t *pIp, kernel_cap_t *pPp) { int ret; + struct task_struct *target; - if (pid && (pid != task_pid_vnr(current))) { - struct task_struct *target; + if (!pid || pid == task_pid_vnr(current)) + return security_capget(current, pEp, pIp, pPp); - spin_lock(&task_capability_lock); - read_lock(&tasklist_lock); + spin_lock(&task_capability_lock); + read_lock(&tasklist_lock); - target = find_task_by_vpid(pid); - if (!target) - ret = -ESRCH; - else - ret = security_capget(target, pEp, pIp, pPp); + target = find_task_by_vpid(pid); + if (!target) + ret = -ESRCH; + else + ret = security_capget(target, pEp, pIp, pPp); - read_unlock(&tasklist_lock); - spin_unlock(&task_capability_lock); - } else - ret = security_capget(current, pEp, pIp, pPp); + read_unlock(&tasklist_lock); + spin_unlock(&task_capability_lock); return ret; } /* - * With filesystem capability support configured, the kernel does not - * permit the changing of capabilities in one process by another - * process. (CAP_SETPCAP has much less broad semantics when configured - * this way.) - */ -static inline int do_sys_capset_other_tasks(pid_t pid, - kernel_cap_t *effective, - kernel_cap_t *inheritable, - kernel_cap_t *permitted) -{ - return -EPERM; -} - -/* * Atomically modify the effective capabilities returning the original * value. No permission check is performed here - it is assumed that the * caller is permitted to set the desired effective capabilities. @@ -293,6 +278,9 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data) if (get_user(pid, &header->pid)) return -EFAULT; + if (pid && (pid != task_pid_vnr(current))) + return -EPERM; + if (copy_from_user(&kdata, data, tocopy * sizeof(struct __user_cap_data_struct))) { return -EFAULT; @@ -310,30 +298,23 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data) i++; } - if (pid && (pid != task_pid_vnr(current))) - ret = do_sys_capset_other_tasks(pid, &effective, &inheritable, - &permitted); - else { - /* - * This lock is required even when filesystem - * capability support is configured - it protects the - * sys_capget() call from returning incorrect data in - * the case that the targeted process is not the - * current one. - */ - spin_lock(&task_capability_lock); + /* + * This lock protects the sys_capget() call from + * returning incorrect data in the case that the targeted + * process is not the current one. + */ + spin_lock(&task_capability_lock); - ret = security_capset_check(current, &effective, &inheritable, - &permitted); - /* - * Having verified that the proposed changes are - * legal, we now put them into effect. - */ - if (!ret) - security_capset_set(current, &effective, &inheritable, - &permitted); - spin_unlock(&task_capability_lock); - } + ret = security_capset_check(current, &effective, &inheritable, + &permitted); + /* + * Having verified that the proposed changes are + * legal, we now put them into effect. + */ + if (!ret) + security_capset_set(current, &effective, &inheritable, + &permitted); + spin_unlock(&task_capability_lock); return ret; -- 1.5.1.1.GIT ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH 4/6] file capabilities: clean up setcap code 2008-09-27 2:27 ` [PATCH 4/6] file capabilities: clean up setcap code Serge E. Hallyn @ 2008-09-27 4:58 ` Andrew G. Morgan 2008-09-27 13:43 ` Serge E. Hallyn 0 siblings, 1 reply; 17+ messages in thread From: Andrew G. Morgan @ 2008-09-27 4:58 UTC (permalink / raw) To: Serge E. Hallyn; +Cc: linux-kernel, linux-security-module -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Serge, I have to say I'm a bit confused by this one. Specifically, the cap_get_target_pid() change. In your 5/6 patch, you say this change ("the previous patch") makes the kernel bigger? Is this because of the cap_get_target_pid() changes? Since you are fighting to reduce space, if it bloats the code does the cap_get_target_pid() part of the change make sense? Cheers Andrew Serge E. Hallyn wrote: > Clean up the sys_capset codepath a bit to account for the fact > that you can now not ever, never, capset on another task. > > Signed-off-by: Serge E. Hallyn <serue@us.ibm.com> > --- > kernel/capability.c | 83 +++++++++++++++++++------------------------------- > 1 files changed, 32 insertions(+), 51 deletions(-) > > diff --git a/kernel/capability.c b/kernel/capability.c > index d39c989..92dd85b 100644 > --- a/kernel/capability.c > +++ b/kernel/capability.c > @@ -132,46 +132,31 @@ static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy) > * process. The net result is that we can limit our use of locks to > * when we are reading the caps of another process. > */ > -static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp, > +static int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp, > kernel_cap_t *pIp, kernel_cap_t *pPp) > { > int ret; > + struct task_struct *target; > > - if (pid && (pid != task_pid_vnr(current))) { > - struct task_struct *target; > + if (!pid || pid == task_pid_vnr(current)) > + return security_capget(current, pEp, pIp, pPp); > > - spin_lock(&task_capability_lock); > - read_lock(&tasklist_lock); > + spin_lock(&task_capability_lock); > + read_lock(&tasklist_lock); > > - target = find_task_by_vpid(pid); > - if (!target) > - ret = -ESRCH; > - else > - ret = security_capget(target, pEp, pIp, pPp); > + target = find_task_by_vpid(pid); > + if (!target) > + ret = -ESRCH; > + else > + ret = security_capget(target, pEp, pIp, pPp); > > - read_unlock(&tasklist_lock); > - spin_unlock(&task_capability_lock); > - } else > - ret = security_capget(current, pEp, pIp, pPp); > + read_unlock(&tasklist_lock); > + spin_unlock(&task_capability_lock); > > return ret; > } > > /* > - * With filesystem capability support configured, the kernel does not > - * permit the changing of capabilities in one process by another > - * process. (CAP_SETPCAP has much less broad semantics when configured > - * this way.) > - */ > -static inline int do_sys_capset_other_tasks(pid_t pid, > - kernel_cap_t *effective, > - kernel_cap_t *inheritable, > - kernel_cap_t *permitted) > -{ > - return -EPERM; > -} > - > -/* > * Atomically modify the effective capabilities returning the original > * value. No permission check is performed here - it is assumed that the > * caller is permitted to set the desired effective capabilities. > @@ -293,6 +278,9 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data) > if (get_user(pid, &header->pid)) > return -EFAULT; > > + if (pid && (pid != task_pid_vnr(current))) > + return -EPERM; > + > if (copy_from_user(&kdata, data, tocopy > * sizeof(struct __user_cap_data_struct))) { > return -EFAULT; > @@ -310,30 +298,23 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data) > i++; > } > > - if (pid && (pid != task_pid_vnr(current))) > - ret = do_sys_capset_other_tasks(pid, &effective, &inheritable, > - &permitted); > - else { > - /* > - * This lock is required even when filesystem > - * capability support is configured - it protects the > - * sys_capget() call from returning incorrect data in > - * the case that the targeted process is not the > - * current one. > - */ > - spin_lock(&task_capability_lock); > + /* > + * This lock protects the sys_capget() call from > + * returning incorrect data in the case that the targeted > + * process is not the current one. > + */ > + spin_lock(&task_capability_lock); > > - ret = security_capset_check(current, &effective, &inheritable, > - &permitted); > - /* > - * Having verified that the proposed changes are > - * legal, we now put them into effect. > - */ > - if (!ret) > - security_capset_set(current, &effective, &inheritable, > - &permitted); > - spin_unlock(&task_capability_lock); > - } > + ret = security_capset_check(current, &effective, &inheritable, > + &permitted); > + /* > + * Having verified that the proposed changes are > + * legal, we now put them into effect. > + */ > + if (!ret) > + security_capset_set(current, &effective, &inheritable, > + &permitted); > + spin_unlock(&task_capability_lock); > > > return ret; -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (Darwin) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFI3b1s+bHCR3gb8jsRAkWCAJ4j5Q5NQc2TD8B+WOYJ1JIqV1GdqQCg1qQU +qzZPOvwo/W/73BuA+HvuxQ= =fRje -----END PGP SIGNATURE----- ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 4/6] file capabilities: clean up setcap code 2008-09-27 4:58 ` Andrew G. Morgan @ 2008-09-27 13:43 ` Serge E. Hallyn 0 siblings, 0 replies; 17+ messages in thread From: Serge E. Hallyn @ 2008-09-27 13:43 UTC (permalink / raw) To: Andrew G. Morgan; +Cc: linux-kernel, linux-security-module Quoting Andrew G. Morgan (morgan@kernel.org): > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Serge, > > I have to say I'm a bit confused by this one. Specifically, the > cap_get_target_pid() change. In your 5/6 patch, you say this change > ("the previous patch") makes the kernel bigger? Is this because of the > cap_get_target_pid() changes? Since you are fighting to reduce space, if > it bloats the code does the cap_get_target_pid() part of the change make > sense? Yes I think it does. Yes my goal was to decrease the kernel size, but having cleaner code - and getting rid of dead codepaths - is more important. It may be hard to tell by looking at the patch, but I think the end-result is really far better. thanks, -serge ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 5/6] file capabilities: remove needless inline functions 2008-09-27 2:27 ` [PATCH 1/6] file capabilities: add no_file_caps switch (v3) Serge E. Hallyn ` (2 preceding siblings ...) 2008-09-27 2:27 ` [PATCH 4/6] file capabilities: clean up setcap code Serge E. Hallyn @ 2008-09-27 2:27 ` Serge E. Hallyn 2008-09-27 4:39 ` Andrew G. Morgan 2008-09-27 2:27 ` [PATCH 6/6] file capabilities: remove needless (?) bprm_clear_caps calls Serge E. Hallyn 4 siblings, 1 reply; 17+ messages in thread From: Serge E. Hallyn @ 2008-09-27 2:27 UTC (permalink / raw) To: linux-kernel; +Cc: linux-security-module, Serge E. Hallyn cap_limit_ptraced_target always returns 1, so nix it. cap_block_setpcap can't return 1 any more, because kernel/capabilities.c:sys_capset() will return -EPERM if it is called on a task other than current, and will never get to cap_capset_check. This brings the vmlinux size with my config down another 16 bytes (making up for the 8 byte increase from the last patch). Signed-off-by: Serge E. Hallyn <serue@us.ibm.com> --- security/commoncap.c | 22 +++------------------- 1 files changed, 3 insertions(+), 19 deletions(-) diff --git a/security/commoncap.c b/security/commoncap.c index d48fdd8..e5afb7c 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -93,15 +93,6 @@ int cap_capget (struct task_struct *target, kernel_cap_t *effective, return 0; } -static inline int cap_block_setpcap(struct task_struct *target) -{ - /* - * No support for remote process capability manipulation with - * filesystem capability support. - */ - return (target != current); -} - static inline int cap_inh_is_capped(void) { /* @@ -112,14 +103,9 @@ static inline int cap_inh_is_capped(void) return (cap_capable(current, CAP_SETPCAP) != 0); } -static inline int cap_limit_ptraced_target(void) { return 1; } - int cap_capset_check (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted) { - if (cap_block_setpcap(target)) { - return -EPERM; - } if (cap_inh_is_capped() && !cap_issubset(*inheritable, cap_combine(target->cap_inheritable, @@ -343,11 +329,9 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) bprm->e_uid = current->uid; bprm->e_gid = current->gid; } - if (cap_limit_ptraced_target()) { - bprm->cap_post_exec_permitted = cap_intersect( - bprm->cap_post_exec_permitted, - current->cap_permitted); - } + bprm->cap_post_exec_permitted = cap_intersect( + bprm->cap_post_exec_permitted, + current->cap_permitted); } } -- 1.5.1.1.GIT ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH 5/6] file capabilities: remove needless inline functions 2008-09-27 2:27 ` [PATCH 5/6] file capabilities: remove needless inline functions Serge E. Hallyn @ 2008-09-27 4:39 ` Andrew G. Morgan 2008-09-27 13:40 ` Serge E. Hallyn 0 siblings, 1 reply; 17+ messages in thread From: Andrew G. Morgan @ 2008-09-27 4:39 UTC (permalink / raw) To: Serge E. Hallyn; +Cc: linux-kernel, linux-security-module -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Serge, I'd much rather simply remove the target argument from the security_capset_check() call. Relying on the caller to not do something bad seems fragile... If the code internally operates on current only, then it doesn't need a target argument... No? (Evidently, such a change is also needed to selinux_capset_check() too, but this doesn't look like it will pose a problem for the selinux code.) Cheers Andrew Serge E. Hallyn wrote: > cap_limit_ptraced_target always returns 1, so nix it. > > cap_block_setpcap can't return 1 any more, because > kernel/capabilities.c:sys_capset() will return -EPERM > if it is called on a task other than current, and will > never get to cap_capset_check. > > This brings the vmlinux size with my config down another > 16 bytes (making up for the 8 byte increase from the > last patch). > > Signed-off-by: Serge E. Hallyn <serue@us.ibm.com> > --- > security/commoncap.c | 22 +++------------------- > 1 files changed, 3 insertions(+), 19 deletions(-) > > diff --git a/security/commoncap.c b/security/commoncap.c > index d48fdd8..e5afb7c 100644 > --- a/security/commoncap.c > +++ b/security/commoncap.c > @@ -93,15 +93,6 @@ int cap_capget (struct task_struct *target, kernel_cap_t *effective, > return 0; > } > > -static inline int cap_block_setpcap(struct task_struct *target) > -{ > - /* > - * No support for remote process capability manipulation with > - * filesystem capability support. > - */ > - return (target != current); > -} > - > static inline int cap_inh_is_capped(void) > { > /* > @@ -112,14 +103,9 @@ static inline int cap_inh_is_capped(void) > return (cap_capable(current, CAP_SETPCAP) != 0); > } > > -static inline int cap_limit_ptraced_target(void) { return 1; } > - > int cap_capset_check (struct task_struct *target, kernel_cap_t *effective, > kernel_cap_t *inheritable, kernel_cap_t *permitted) > { > - if (cap_block_setpcap(target)) { > - return -EPERM; > - } > if (cap_inh_is_capped() > && !cap_issubset(*inheritable, > cap_combine(target->cap_inheritable, > @@ -343,11 +329,9 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) > bprm->e_uid = current->uid; > bprm->e_gid = current->gid; > } > - if (cap_limit_ptraced_target()) { > - bprm->cap_post_exec_permitted = cap_intersect( > - bprm->cap_post_exec_permitted, > - current->cap_permitted); > - } > + bprm->cap_post_exec_permitted = cap_intersect( > + bprm->cap_post_exec_permitted, > + current->cap_permitted); > } > } > -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (Darwin) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFI3bjz+bHCR3gb8jsRAqJpAJ9Ca1pADkG5BnGoOVZA+EmZbuRPfgCgoQ95 ljvsvj7Ssp+0mXDuCy0/TnU= =79ni -----END PGP SIGNATURE----- ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 5/6] file capabilities: remove needless inline functions 2008-09-27 4:39 ` Andrew G. Morgan @ 2008-09-27 13:40 ` Serge E. Hallyn 2008-09-29 21:53 ` Serge E. Hallyn 0 siblings, 1 reply; 17+ messages in thread From: Serge E. Hallyn @ 2008-09-27 13:40 UTC (permalink / raw) To: Andrew G. Morgan; +Cc: linux-kernel, linux-security-module Quoting Andrew G. Morgan (morgan@kernel.org): > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Serge, > > I'd much rather simply remove the target argument from the > security_capset_check() call. Relying on the caller to not do something Yes, I did do that in a patch on top of all of these. It increased the kernel size by 8 (or was it 16) bytes :) I assume that was because now there were more references to 'current' which is inlined? So I should be able to fix that by saving current() away at the top of the fn. Will try that. thanks, -serge > bad seems fragile... If the code internally operates on current only, > then it doesn't need a target argument... No? (Evidently, such a change > is also needed to selinux_capset_check() too, but this doesn't look like > it will pose a problem for the selinux code.) > > Cheers > > Andrew > > Serge E. Hallyn wrote: > > cap_limit_ptraced_target always returns 1, so nix it. > > > > cap_block_setpcap can't return 1 any more, because > > kernel/capabilities.c:sys_capset() will return -EPERM > > if it is called on a task other than current, and will > > never get to cap_capset_check. > > > > This brings the vmlinux size with my config down another > > 16 bytes (making up for the 8 byte increase from the > > last patch). > > > > Signed-off-by: Serge E. Hallyn <serue@us.ibm.com> > > --- > > security/commoncap.c | 22 +++------------------- > > 1 files changed, 3 insertions(+), 19 deletions(-) > > > > diff --git a/security/commoncap.c b/security/commoncap.c > > index d48fdd8..e5afb7c 100644 > > --- a/security/commoncap.c > > +++ b/security/commoncap.c > > @@ -93,15 +93,6 @@ int cap_capget (struct task_struct *target, kernel_cap_t *effective, > > return 0; > > } > > > > -static inline int cap_block_setpcap(struct task_struct *target) > > -{ > > - /* > > - * No support for remote process capability manipulation with > > - * filesystem capability support. > > - */ > > - return (target != current); > > -} > > - > > static inline int cap_inh_is_capped(void) > > { > > /* > > @@ -112,14 +103,9 @@ static inline int cap_inh_is_capped(void) > > return (cap_capable(current, CAP_SETPCAP) != 0); > > } > > > > -static inline int cap_limit_ptraced_target(void) { return 1; } > > - > > int cap_capset_check (struct task_struct *target, kernel_cap_t *effective, > > kernel_cap_t *inheritable, kernel_cap_t *permitted) > > { > > - if (cap_block_setpcap(target)) { > > - return -EPERM; > > - } > > if (cap_inh_is_capped() > > && !cap_issubset(*inheritable, > > cap_combine(target->cap_inheritable, > > @@ -343,11 +329,9 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) > > bprm->e_uid = current->uid; > > bprm->e_gid = current->gid; > > } > > - if (cap_limit_ptraced_target()) { > > - bprm->cap_post_exec_permitted = cap_intersect( > > - bprm->cap_post_exec_permitted, > > - current->cap_permitted); > > - } > > + bprm->cap_post_exec_permitted = cap_intersect( > > + bprm->cap_post_exec_permitted, > > + current->cap_permitted); > > } > > } > > > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1.4.7 (Darwin) > Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org > > iD8DBQFI3bjz+bHCR3gb8jsRAqJpAJ9Ca1pADkG5BnGoOVZA+EmZbuRPfgCgoQ95 > ljvsvj7Ssp+0mXDuCy0/TnU= > =79ni > -----END PGP SIGNATURE----- ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 5/6] file capabilities: remove needless inline functions 2008-09-27 13:40 ` Serge E. Hallyn @ 2008-09-29 21:53 ` Serge E. Hallyn 0 siblings, 0 replies; 17+ messages in thread From: Serge E. Hallyn @ 2008-09-29 21:53 UTC (permalink / raw) To: Andrew G. Morgan; +Cc: linux-kernel, linux-security-module Quoting Serge E. Hallyn (serue@us.ibm.com): > Quoting Andrew G. Morgan (morgan@kernel.org): > > -----BEGIN PGP SIGNED MESSAGE----- > > Hash: SHA1 > > > > Serge, > > > > I'd much rather simply remove the target argument from the > > security_capset_check() call. Relying on the caller to not do something > > Yes, I did do that in a patch on top of all of these. It increased the > kernel size by 8 (or was it 16) bytes :) I assume that was because > now there were more references to 'current' which is inlined? So I > should be able to fix that by saving current() away at the top of > the fn. > > Will try that. > > thanks, > -serge > > > bad seems fragile... If the code internally operates on current only, > > then it doesn't need a target argument... No? (Evidently, such a change > > is also needed to selinux_capset_check() too, but this doesn't look like > > it will pose a problem for the selinux code.) Here is a patch (on top of the others) doing that. thanks, -serge Subject: [PATCH] capabilities: remove target argument from capset_check and set Since it is no longer possible to set capabilities on another task, remove the 'target' option from capset_set and capset_check. Since the userspace API shouldn't change, we maintain 'pid' as a valid option to the actual sys_capset(), continuing to return -EPERM when pid is not current's pid. Signed-off-by: Serge E. Hallyn <serue@us.ibm.com> --- include/linux/security.h | 49 ++++++++++++++++------------------------------ kernel/capability.c | 6 ++---- security/commoncap.c | 29 +++++++++++++++------------ security/security.c | 18 ++++++++--------- security/selinux/hooks.c | 15 ++++++++------ 5 files changed, 51 insertions(+), 66 deletions(-) 35b1a7906d26fd10da34e5cd350470abb812a91c diff --git a/include/linux/security.h b/include/linux/security.h index 80c4d00..7b9f7a2 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -49,8 +49,8 @@ extern int cap_settime(struct timespec * extern int cap_ptrace_may_access(struct task_struct *child, unsigned int mode); extern int cap_ptrace_traceme(struct task_struct *parent); extern int cap_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); -extern int cap_capset_check(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); -extern void cap_capset_set(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); +extern int cap_capset_check(kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); +extern void cap_capset_set(kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); extern int cap_bprm_set_security(struct linux_binprm *bprm); extern void cap_bprm_apply_creds(struct linux_binprm *bprm, int unsafe); extern int cap_bprm_secureexec(struct linux_binprm *bprm); @@ -1187,24 +1187,15 @@ static inline void security_free_mnt_opt * Return 0 if the capability sets were successfully obtained. * @capset_check: * Check permission before setting the @effective, @inheritable, and - * @permitted capability sets for the @target process. - * Caveat: @target is also set to current if a set of processes is - * specified (i.e. all processes other than current and init or a - * particular process group). Hence, the capset_set hook may need to - * revalidate permission to the actual target process. - * @target contains the task_struct structure for target process. + * @permitted capability sets for the current process. * @effective contains the effective capability set. * @inheritable contains the inheritable capability set. * @permitted contains the permitted capability set. * Return 0 if permission is granted. * @capset_set: * Set the @effective, @inheritable, and @permitted capability sets for - * the @target process. Since capset_check cannot always check permission - * to the real @target process, this hook may also perform permission - * checking to determine if the current process is allowed to set the - * capability sets of the @target process. However, this hook has no way - * of returning an error due to the structure of the sys_capset code. - * @target contains the task_struct structure for target process. + * the current process. This hook has no way of returning an error due to + * the structure of the sys_capset code. * @effective contains the effective capability set. * @inheritable contains the inheritable capability set. * @permitted contains the permitted capability set. @@ -1299,12 +1290,10 @@ struct security_operations { int (*capget) (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); - int (*capset_check) (struct task_struct *target, - kernel_cap_t *effective, + int (*capset_check) (kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); - void (*capset_set) (struct task_struct *target, - kernel_cap_t *effective, + void (*capset_set) (kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); int (*capable) (struct task_struct *tsk, int cap); @@ -1573,12 +1562,10 @@ int security_capget(struct task_struct * kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); -int security_capset_check(struct task_struct *target, - kernel_cap_t *effective, +int security_capset_check(kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); -void security_capset_set(struct task_struct *target, - kernel_cap_t *effective, +void security_capset_set(kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); int security_capable(struct task_struct *tsk, int cap); @@ -1768,20 +1755,18 @@ static inline int security_capget(struct return cap_capget(target, effective, inheritable, permitted); } -static inline int security_capset_check(struct task_struct *target, - kernel_cap_t *effective, - kernel_cap_t *inheritable, - kernel_cap_t *permitted) +static inline int security_capset_check(kernel_cap_t *effective, + kernel_cap_t *inheritable, + kernel_cap_t *permitted) { - return cap_capset_check(target, effective, inheritable, permitted); + return cap_capset_check(effective, inheritable, permitted); } -static inline void security_capset_set(struct task_struct *target, - kernel_cap_t *effective, - kernel_cap_t *inheritable, - kernel_cap_t *permitted) +static inline void security_capset_set(kernel_cap_t *effective, + kernel_cap_t *inheritable, + kernel_cap_t *permitted) { - cap_capset_set(target, effective, inheritable, permitted); + cap_capset_set(effective, inheritable, permitted); } static inline int security_capable(struct task_struct *tsk, int cap) diff --git a/kernel/capability.c b/kernel/capability.c index 92dd85b..f119288 100644 --- a/kernel/capability.c +++ b/kernel/capability.c @@ -305,15 +305,13 @@ asmlinkage long sys_capset(cap_user_head */ spin_lock(&task_capability_lock); - ret = security_capset_check(current, &effective, &inheritable, - &permitted); + ret = security_capset_check(&effective, &inheritable, &permitted); /* * Having verified that the proposed changes are * legal, we now put them into effect. */ if (!ret) - security_capset_set(current, &effective, &inheritable, - &permitted); + security_capset_set(&effective, &inheritable, &permitted); spin_unlock(&task_capability_lock); diff --git a/security/commoncap.c b/security/commoncap.c index 43bba7a..031bb90 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -103,27 +103,29 @@ static inline int cap_inh_is_capped(void return (cap_capable(current, CAP_SETPCAP) != 0); } -int cap_capset_check (struct task_struct *target, kernel_cap_t *effective, - kernel_cap_t *inheritable, kernel_cap_t *permitted) +int cap_capset_check (kernel_cap_t *effective, kernel_cap_t *inheritable, + kernel_cap_t *permitted) { + struct task_struct *t = current; + if (cap_inh_is_capped() && !cap_issubset(*inheritable, - cap_combine(target->cap_inheritable, - current->cap_permitted))) { + cap_combine(t->cap_inheritable, + t->cap_permitted))) { /* incapable of using this inheritable set */ return -EPERM; } if (!cap_issubset(*inheritable, - cap_combine(target->cap_inheritable, - current->cap_bset))) { + cap_combine(t->cap_inheritable, + t->cap_bset))) { /* no new pI capabilities outside bounding set */ return -EPERM; } /* verify restrictions on target's new Permitted set */ if (!cap_issubset (*permitted, - cap_combine (target->cap_permitted, - current->cap_permitted))) { + cap_combine (t->cap_permitted, + t->cap_permitted))) { return -EPERM; } @@ -135,12 +137,13 @@ int cap_capset_check (struct task_struct return 0; } -void cap_capset_set (struct task_struct *target, kernel_cap_t *effective, - kernel_cap_t *inheritable, kernel_cap_t *permitted) +void cap_capset_set (kernel_cap_t *effective, kernel_cap_t *inheritable, + kernel_cap_t *permitted) { - target->cap_effective = *effective; - target->cap_inheritable = *inheritable; - target->cap_permitted = *permitted; + struct task_struct *t = current; + t->cap_effective = *effective; + t->cap_inheritable = *inheritable; + t->cap_permitted = *permitted; } static inline void bprm_clear_caps(struct linux_binprm *bprm) diff --git a/security/security.c b/security/security.c index 3a4b4f5..78502ac 100644 --- a/security/security.c +++ b/security/security.c @@ -145,20 +145,18 @@ int security_capget(struct task_struct * return security_ops->capget(target, effective, inheritable, permitted); } -int security_capset_check(struct task_struct *target, - kernel_cap_t *effective, - kernel_cap_t *inheritable, - kernel_cap_t *permitted) +int security_capset_check(kernel_cap_t *effective, + kernel_cap_t *inheritable, + kernel_cap_t *permitted) { - return security_ops->capset_check(target, effective, inheritable, permitted); + return security_ops->capset_check(effective, inheritable, permitted); } -void security_capset_set(struct task_struct *target, - kernel_cap_t *effective, - kernel_cap_t *inheritable, - kernel_cap_t *permitted) +void security_capset_set(kernel_cap_t *effective, + kernel_cap_t *inheritable, + kernel_cap_t *permitted) { - security_ops->capset_set(target, effective, inheritable, permitted); + security_ops->capset_set(effective, inheritable, permitted); } int security_capable(struct task_struct *tsk, int cap) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 03fc6a8..d06e943 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1780,22 +1780,23 @@ static int selinux_capget(struct task_st return secondary_ops->capget(target, effective, inheritable, permitted); } -static int selinux_capset_check(struct task_struct *target, kernel_cap_t *effective, - kernel_cap_t *inheritable, kernel_cap_t *permitted) +static int selinux_capset_check(kernel_cap_t *effective, kernel_cap_t *inheritable, + kernel_cap_t *permitted) { int error; + struct task_struct *t = current; - error = secondary_ops->capset_check(target, effective, inheritable, permitted); + error = secondary_ops->capset_check(effective, inheritable, permitted); if (error) return error; - return task_has_perm(current, target, PROCESS__SETCAP); + return task_has_perm(t, t, PROCESS__SETCAP); } -static void selinux_capset_set(struct task_struct *target, kernel_cap_t *effective, - kernel_cap_t *inheritable, kernel_cap_t *permitted) +static void selinux_capset_set(kernel_cap_t *effective, kernel_cap_t *inheritable, + kernel_cap_t *permitted) { - secondary_ops->capset_set(target, effective, inheritable, permitted); + secondary_ops->capset_set(effective, inheritable, permitted); } static int selinux_capable(struct task_struct *tsk, int cap) -- 1.1.6 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 6/6] file capabilities: remove needless (?) bprm_clear_caps calls 2008-09-27 2:27 ` [PATCH 1/6] file capabilities: add no_file_caps switch (v3) Serge E. Hallyn ` (3 preceding siblings ...) 2008-09-27 2:27 ` [PATCH 5/6] file capabilities: remove needless inline functions Serge E. Hallyn @ 2008-09-27 2:27 ` Serge E. Hallyn 2008-09-27 2:27 ` Serge E. Hallyn 4 siblings, 1 reply; 17+ messages in thread From: Serge E. Hallyn @ 2008-09-27 2:27 UTC (permalink / raw) To: linux-kernel; +Cc: linux-security-module, Serge E. Hallyn Two error conditions at the top of get_file_caps() call bprm_clear_caps(). However, the bprm capabilities have not yet been set at this point. Remove those calls (saving another 16 bytes on vmlinux). Signed-off-by: Serge E. Hallyn <serue@us.ibm.com> --- security/commoncap.c | 8 ++------ 1 files changed, 2 insertions(+), 6 deletions(-) diff --git a/security/commoncap.c b/security/commoncap.c index e5afb7c..43bba7a 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -250,15 +250,11 @@ static int get_file_caps(struct linux_binprm *bprm) struct vfs_cap_data vcaps; struct inode *inode; - if (!file_caps_enabled) { - bprm_clear_caps(bprm); + if (!file_caps_enabled) return 0; - } - if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) { - bprm_clear_caps(bprm); + if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) return 0; - } dentry = dget(bprm->file->f_dentry); inode = dentry->d_inode; -- 1.5.1.1.GIT ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 6/6] file capabilities: remove needless (?) bprm_clear_caps calls 2008-09-27 2:27 ` [PATCH 6/6] file capabilities: remove needless (?) bprm_clear_caps calls Serge E. Hallyn @ 2008-09-27 2:27 ` Serge E. Hallyn 2008-09-27 2:27 ` Serge E. Hallyn 0 siblings, 1 reply; 17+ messages in thread From: Serge E. Hallyn @ 2008-09-27 2:27 UTC (permalink / raw) To: linux-kernel; +Cc: linux-security-module Andrew Morgan, if you have a moment, please do take a close look and make sure I'm not doing anything stupid/wrong in the cleanups! However ltp shows no difference with and without the patchset. Following are the kernel sizes after some of the patches. original, pre-patch, with file capabilities compiled out: text data bss dec hex filename 4188468 234432 316472 4739372 48512c vmlinux original, pre-patch, with file capabilities compiled in: 4189356 234432 316472 4740260 4854a4 vmlinux plain with fcaps always-on: 4189392 234456 316472 4740320 4854e0 vmlinux with non-inline cap_safe_nice: 4189112 234456 316472 4740040 4853c8 vmlinux with cleaned-up setcap: 4189120 234456 316472 4740048 4853d0 vmlinux with needless check for target!=current removed from cap_capset: 4189104 234456 316472 4740032 4853c0 vmlinux with needless(?) bprm_clear_caps calls removed: 4189088 234456 316472 4740016 4853b0 vmlinux thanks, -serge ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 6/6] file capabilities: remove needless (?) bprm_clear_caps calls 2008-09-27 2:27 ` Serge E. Hallyn @ 2008-09-27 2:27 ` Serge E. Hallyn 0 siblings, 0 replies; 17+ messages in thread From: Serge E. Hallyn @ 2008-09-27 2:27 UTC (permalink / raw) To: linux-kernel; +Cc: linux-security-module ^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2008-09-29 21:54 UTC | newest] Thread overview: 17+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-09-27 2:27 [PATCH 0/6] file capabilities cleanups: introduction Serge E. Hallyn 2008-09-27 2:27 ` [PATCH 1/6] file capabilities: add no_file_caps switch (v3) Serge E. Hallyn 2008-09-27 2:27 ` [PATCH 2/6] file capabilities: remove CONFIG_SECURITY_FILE_CAPABILITIES Serge E. Hallyn 2008-09-27 4:25 ` Andrew G. Morgan 2008-09-27 2:27 ` [PATCH 3/6] file capabilities: uninline cap_safe_nice Serge E. Hallyn 2008-09-27 4:26 ` Andrew G. Morgan 2008-09-27 5:27 ` James Morris 2008-09-27 2:27 ` [PATCH 4/6] file capabilities: clean up setcap code Serge E. Hallyn 2008-09-27 4:58 ` Andrew G. Morgan 2008-09-27 13:43 ` Serge E. Hallyn 2008-09-27 2:27 ` [PATCH 5/6] file capabilities: remove needless inline functions Serge E. Hallyn 2008-09-27 4:39 ` Andrew G. Morgan 2008-09-27 13:40 ` Serge E. Hallyn 2008-09-29 21:53 ` Serge E. Hallyn 2008-09-27 2:27 ` [PATCH 6/6] file capabilities: remove needless (?) bprm_clear_caps calls Serge E. Hallyn 2008-09-27 2:27 ` Serge E. Hallyn 2008-09-27 2:27 ` Serge E. Hallyn
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox