Messages in this thread Patch in this message | | | Date | Mon, 28 Aug 2006 16:39:12 -0500 | From | "Serge E. Hallyn" <> | Subject | Re: [RFC] [PATCH] file posix capabilities |
| |
The following patch addresses remaining LSM hooks which need to be handled in the face of file capabilities. This is on top of the cap_bprm_secureexec patch in the email I had replied to.
-serge
From 7ee4dafddb85d6ccf34ddc50e2a44b244bb4b6b3 Mon Sep 17 00:00:00 2001 From: Serge E. Hallyn <serue@us.ibm.com> Date: Mon, 28 Aug 2006 14:39:57 -0500 Subject: [PATCH 3/3] fscaps: define task_kill and other new capchecks
task_setrlimit, task_prctl, and task_movememory are not a problem with fscaps. This patch defines task_setscheduler, task_setioprio, cap_task_kill, and task_setnice to make sure a user cannot affect a process in which they called a program with some fscaps.
One remaining question is the note under task_setscheduler: are we ok with CAP_SYS_NICE being sufficient to confine a process to a cpuset?
It is a semantic change, as without fsccaps, attach_task doesn't allow CAP_SYS_NICE to override the uid equivalence check. But since it uses security_task_setscheduler, which elsewhere is used where CAP_SYS_NICE can be used to override the uid equivalence check, fixing it might be tough.
task_setscheduler need to check for !capable(CAP_SYS_NICE) && current->euid==p->euid && !cap_subset(current->caps, p->caps) where p->caps are not subset of current->caps note: this also controls cpuset:attach_task. Are we ok with CAP_SYS_NICE being used to confine to a cpuset? task_setioprio Same check as task_setscheduler task_setnice sys_setpriority uses this (through set_one_prio) for another process. Need same checks as setrlimit
no need: task_setrlimit affect only calling task task_prctl (set_dumpable, set_keepcaps) affect only calling task task_movememory CAP_SYS_NICE is already checked
Signed-off-by: Serge E. Hallyn <serue@us.ibm.com> --- include/linux/security.h | 10 +++++-- security/capability.c | 4 +++ security/commoncap.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 3 deletions(-)
diff --git a/include/linux/security.h b/include/linux/security.h index f753038..7a99930 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -51,6 +51,10 @@ extern int cap_inode_setxattr(struct den extern int cap_inode_removexattr(struct dentry *dentry, char *name); extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags); extern void cap_task_reparent_to_init (struct task_struct *p); +extern int cap_task_kill(struct task_struct *p, struct siginfo *info, int sig, u32 secid); +extern int cap_task_setscheduler (struct task_struct *p, int policy, struct sched_param *lp); +extern int cap_task_setioprio (struct task_struct *p, int ioprio); +extern int cap_task_setnice (struct task_struct *p, int nice); extern int cap_syslog (int type); extern int cap_vm_enough_memory (long pages); @@ -2522,12 +2526,12 @@ static inline int security_task_setgroup static inline int security_task_setnice (struct task_struct *p, int nice) { - return 0; + return cap_task_setnice(p, nice); } static inline int security_task_setioprio (struct task_struct *p, int ioprio) { - return 0; + return cap_task_setioprio(p, ioprio); } static inline int security_task_getioprio (struct task_struct *p) @@ -2562,7 +2566,7 @@ static inline int security_task_kill (st struct siginfo *info, int sig, u32 secid) { - return 0; + return cap_task_kill(p, info, sig, secid); } static inline int security_task_wait (struct task_struct *p) diff --git a/security/capability.c b/security/capability.c index b868e7e..14cb592 100644 --- a/security/capability.c +++ b/security/capability.c @@ -40,6 +40,10 @@ static struct security_operations capabi .inode_setxattr = cap_inode_setxattr, .inode_removexattr = cap_inode_removexattr, + .task_kill = cap_task_kill, + .task_setscheduler = cap_task_setscheduler, + .task_setioprio = cap_task_setioprio, + .task_setnice = cap_task_setnice, .task_post_setuid = cap_task_post_setuid, .task_reparent_to_init = cap_task_reparent_to_init, diff --git a/security/commoncap.c b/security/commoncap.c index b1777a9..82bd59f 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -387,6 +387,64 @@ int cap_task_post_setuid (uid_t old_ruid return 0; } +/* + * Rationale: code calling task_setscheduler, task_setioprio, and + * task_setnice, assumes that + * . if capable(cap_sys_nice), then those actions should be allowed + * . if not capable(cap_sys_nice), but acting on your own processes, + * then those actions should be allowed + * This is insufficient now since you can call code without suid, but + * yet with increased caps. + * So we check for increased caps on the target process. + */ +static inline int cap_safe_nice(struct task_struct *p) +{ + if (!cap_issubset(p->cap_permitted, current->cap_permitted) && + !__capable(current, CAP_SYS_NICE)) + return -EPERM; + return 0; +} + +int cap_task_setscheduler (struct task_struct *p, int policy, + struct sched_param *lp) +{ + return cap_safe_nice(p); +} + +int cap_task_setioprio (struct task_struct *p, int ioprio) +{ + return cap_safe_nice(p); +} + +int cap_task_setnice (struct task_struct *p, int nice) +{ + return cap_safe_nice(p); +} + +int cap_task_kill(struct task_struct *p, struct siginfo *info, + int sig, u32 secid) +{ + if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info))) + return 0; + + if (secid) + /* + * Signal sent as a particular user. + * Capabilities are ignored. May be wrong, but it's the + * only thing we can do at the moment. + * Used only by usb drivers? + */ + return 0; + if (current->uid == 0 || current->euid == 0) + return 0; + if (capable(CAP_KILL)) + return 0; + if (cap_issubset(p->cap_permitted, current->cap_permitted)) + return 0; + + return -EPERM; +} + void cap_task_reparent_to_init (struct task_struct *p) { p->cap_effective = CAP_INIT_EFF_SET; @@ -424,6 +482,10 @@ EXPORT_SYMBOL(cap_bprm_secureexec); EXPORT_SYMBOL(cap_inode_setxattr); EXPORT_SYMBOL(cap_inode_removexattr); EXPORT_SYMBOL(cap_task_post_setuid); +EXPORT_SYMBOL(cap_task_kill); +EXPORT_SYMBOL(cap_task_setscheduler); +EXPORT_SYMBOL(cap_task_setioprio); +EXPORT_SYMBOL(cap_task_setnice); EXPORT_SYMBOL(cap_task_reparent_to_init); EXPORT_SYMBOL(cap_syslog); EXPORT_SYMBOL(cap_vm_enough_memory); -- 1.4.2 - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |