|
Message-ID: <20110619141810.GA3708@albatros> Date: Sun, 19 Jun 2011 18:18:10 +0400 From: Vasiliy Kulikov <segoon@...nwall.com> To: kernel-hardening@...ts.openwall.com Subject: Re: proc info restrictions problem On Sat, Jun 18, 2011 at 22:28 +0400, Vasiliy Kulikov wrote: > Another choise - remove hidepid=2 at all. The patch for hidepid=1 only is as follows: (tested with /proc exploring and using a sample taskstats program Documentation/accounting/getdelays.c) diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index 5e7cb39..f023e1e 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -52,6 +52,8 @@ show up in /proc/sys/kernel: - powersave-nap [ PPC only ] - panic_on_unrecovered_nmi - printk +- procinfo_restricted +- procinfo_restricted_gid - randomize_va_space - real-root-dev ==> Documentation/initrd.txt - reboot-cmd [ SPARC only ] @@ -403,6 +405,31 @@ Value from 0 - 10000 is allowed. ============================================================== +procinfo_restricted: + +This option defined how much information about processes we want to be +available for non-owners: + +0 - No process information is additionally restricted. Common procfs + and taskstats access rules are applied. + +1 - Users may not get any statistics or debugging information about any + processes, but their own. Process name and command line are + restricted too. Users may not access aliens' /proc/<pid>/ + directories or get any information about aliens' processes via + taskstats. + +============================================================== + +procinfo_restricted_gid: + +Defines a group number. All members of this group are allowed to gather +process' information bypassing procinfo_restricted. If you use identd +or similar daemon that wants to learn processes information, just add +the daemon's user to this group. + +============================================================== + randomize-va-space: This option can be used to select the type of process address diff --git a/fs/proc/base.c b/fs/proc/base.c index 14def99..5fa8d83 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -627,8 +627,19 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr) return 0; } +static int proc_pid_permission(struct inode *inode, int mask, + unsigned int flags) +{ + struct task_struct *task = get_proc_task(inode); + + if (!procinfo_may_stat_task(task)) + return -EACCES; + return generic_permission(inode, mask, flags, NULL); +} + static const struct inode_operations proc_def_inode_operations = { .setattr = proc_setattr, + .permission = proc_pid_permission, }; static int mounts_open_common(struct inode *inode, struct file *file, @@ -1670,6 +1681,7 @@ static const struct inode_operations proc_pid_link_inode_operations = { .readlink = proc_pid_readlink, .follow_link = proc_pid_follow_link, .setattr = proc_setattr, + .permission = proc_pid_permission, }; @@ -2872,6 +2884,7 @@ static const struct inode_operations proc_tgid_base_inode_operations = { .lookup = proc_tgid_base_lookup, .getattr = pid_getattr, .setattr = proc_setattr, + .permission = proc_pid_permission, }; static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid) diff --git a/include/linux/capability.h b/include/linux/capability.h index c421123..cc0bcfe 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -544,7 +544,9 @@ extern bool has_ns_capability(struct task_struct *t, struct user_namespace *ns, int cap); extern bool has_capability_noaudit(struct task_struct *t, int cap); extern bool capable(int cap); +extern bool task_capable(struct task_struct *task, int cap); extern bool ns_capable(struct user_namespace *ns, int cap); +extern bool ns_task_capable(struct task_struct *t, struct user_namespace *ns, int cap); extern bool task_ns_capable(struct task_struct *t, int cap); extern bool nsown_capable(int cap); diff --git a/include/linux/cred.h b/include/linux/cred.h index 8260799..e910948 100644 --- a/include/linux/cred.h +++ b/include/linux/cred.h @@ -73,6 +73,7 @@ extern int groups_search(const struct group_info *, gid_t); ((gi)->blocks[(i) / NGROUPS_PER_BLOCK][(i) % NGROUPS_PER_BLOCK]) extern int in_group_p(gid_t); +extern int task_in_group_p(struct task_struct *task, gid_t grp); extern int in_egroup_p(gid_t); /* diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h index 38d1032..ab937c9 100644 --- a/include/linux/pid_namespace.h +++ b/include/linux/pid_namespace.h @@ -6,12 +6,27 @@ #include <linux/threads.h> #include <linux/nsproxy.h> #include <linux/kref.h> +#include <linux/ptrace.h> struct pidmap { atomic_t nr_free; void *page; }; +enum procinfo_restricted { + /* + * Classical mode, no process information is additionally restricted. + */ + PROCINFO_NONE = 0, + + /* + * Users may not learn other users' processess statistics, + * debug information, cmdline and comm. Credentials information + * is not restricted. + */ + PROCINFO_STATS = 1, +}; + #define PIDMAP_ENTRIES ((PID_MAX_LIMIT + 8*PAGE_SIZE - 1)/PAGE_SIZE/8) struct bsd_acct_struct; @@ -30,6 +45,8 @@ struct pid_namespace { #ifdef CONFIG_BSD_PROCESS_ACCT struct bsd_acct_struct *bacct; #endif + enum procinfo_restricted procinfo_restricted; + gid_t procinfo_restricted_gid; }; extern struct pid_namespace init_pid_ns; @@ -83,4 +100,51 @@ extern struct pid_namespace *task_active_pid_ns(struct task_struct *tsk); void pidhash_init(void); void pidmap_init(void); +static inline bool procinfo_may_access_task(struct task_struct *tsk, enum procinfo_restricted pr) +{ + struct pid_namespace *ns; + + if (current->nsproxy == NULL || current->nsproxy->pid_ns == NULL) + return false; + ns = current->nsproxy->pid_ns; + + return (ns->procinfo_restricted < pr) || + in_group_p(ns->procinfo_restricted_gid) || + ptrace_may_access(tsk, PTRACE_MODE_READ); +} + +static inline bool procinfo_task_may_access_current(struct task_struct *tsk, enum procinfo_restricted pr) +{ + struct pid_namespace *ns; + + if (current->nsproxy == NULL || current->nsproxy->pid_ns == NULL) + return false; + ns = current->nsproxy->pid_ns; + + return (ns->procinfo_restricted < pr) || + task_in_group_p(tsk, ns->procinfo_restricted_gid) || + ptrace_task_may_access_current(tsk, PTRACE_MODE_READ); +} + +static inline bool procinfo_task_may_stat_current(struct task_struct *tsk) +{ + int res; + pr_err("check whether %lu may stat %lu...\n", + (unsigned long)tsk->pid, (unsigned long)current->pid); + res = procinfo_task_may_access_current(tsk, PROCINFO_STATS); + pr_err( "%s\n", res ? "yes" : "no"); + return res; +} + +static inline bool procinfo_may_stat_task(struct task_struct *tsk) +{ + int res; + pr_err( "check whether %lu may stat %lu...\n", + (unsigned long)current->pid, + (unsigned long)tsk->pid); + res = procinfo_may_access_task(tsk, PROCINFO_STATS); + pr_err( "%s\n", res ? "yes" : "no"); + return res; +} + #endif /* _LINUX_PID_NS_H */ diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index 9178d5c..bb59e43 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -116,9 +116,10 @@ extern void exit_ptrace(struct task_struct *tracer); #define PTRACE_MODE_READ 1 #define PTRACE_MODE_ATTACH 2 /* Returns 0 on success, -errno on denial. */ -extern int __ptrace_may_access(struct task_struct *task, unsigned int mode); +extern int __ptrace_may_access(struct task_struct *who, struct task_struct *task, unsigned int mode); /* Returns true on success, false on denial. */ extern bool ptrace_may_access(struct task_struct *task, unsigned int mode); +extern bool ptrace_task_may_access_current(struct task_struct *task, unsigned int mode); static inline int ptrace_reparented(struct task_struct *child) { diff --git a/include/linux/security.h b/include/linux/security.h index 8ce59ef..fb79dd5 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -56,7 +56,8 @@ struct user_namespace; extern int cap_capable(struct task_struct *tsk, const struct cred *cred, struct user_namespace *ns, int cap, int audit); extern int cap_settime(const struct timespec *ts, const struct timezone *tz); -extern int cap_ptrace_access_check(struct task_struct *child, unsigned int mode); +extern int cap_ptrace_access_check(struct task_struct *task, 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(struct cred *new, const struct cred *old, @@ -1375,7 +1376,9 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) struct security_operations { char name[SECURITY_NAME_MAX + 1]; - int (*ptrace_access_check) (struct task_struct *child, unsigned int mode); + int (*ptrace_access_check) (struct task_struct *task, + struct task_struct *child, + unsigned int mode); int (*ptrace_traceme) (struct task_struct *parent); int (*capget) (struct task_struct *target, kernel_cap_t *effective, @@ -1657,6 +1660,8 @@ extern int security_module_enable(struct security_operations *ops); extern int register_security(struct security_operations *ops); /* Security operations */ +int security_ptrace_task_access_check(struct task_struct *task, + struct task_struct *child, unsigned int mode); int security_ptrace_access_check(struct task_struct *child, unsigned int mode); int security_ptrace_traceme(struct task_struct *parent); int security_capget(struct task_struct *target, @@ -1667,6 +1672,10 @@ int security_capset(struct cred *new, const struct cred *old, const kernel_cap_t *effective, const kernel_cap_t *inheritable, const kernel_cap_t *permitted); +int security_task_capable(struct task_struct *task, + struct user_namespace *ns, + const struct cred *cred, + int cap); int security_capable(struct user_namespace *ns, const struct cred *cred, int cap); int security_real_capable(struct task_struct *tsk, struct user_namespace *ns, @@ -1837,10 +1846,16 @@ static inline int security_init(void) return 0; } +static inline int security_ptrace_task_access_check(struct task_struct *task, + struct task_struct *child, unsigned int mode) +{ + return cap_ptrace_access_check(task, child, mode); +} + static inline int security_ptrace_access_check(struct task_struct *child, unsigned int mode) { - return cap_ptrace_access_check(child, mode); + return cap_ptrace_access_check(current, child, mode); } static inline int security_ptrace_traceme(struct task_struct *parent) @@ -1865,10 +1880,18 @@ static inline int security_capset(struct cred *new, return cap_capset(new, old, effective, inheritable, permitted); } +static inline int security_task_capable(struct task_struct *task, + struct user_namespace *ns, + const struct cred *cred, + int cap) +{ + return cap_capable(task, cred, ns, cap, SECURITY_CAP_AUDIT); +} + static inline int security_capable(struct user_namespace *ns, const struct cred *cred, int cap) { - return cap_capable(current, cred, ns, cap, SECURITY_CAP_AUDIT); + return security_task_capable(current, ns, cred, cap); } static inline int security_real_capable(struct task_struct *tsk, struct user_namespace *ns, int cap) diff --git a/kernel/capability.c b/kernel/capability.c index 283c529..93c82fe 100644 --- a/kernel/capability.c +++ b/kernel/capability.c @@ -356,6 +356,30 @@ bool capable(int cap) } EXPORT_SYMBOL(capable); +bool task_capable(struct task_struct *task, int cap) +{ + return ns_task_capable(task, &init_user_ns, cap); +} +EXPORT_SYMBOL(task_capable); + +bool ns_task_capable(struct task_struct *task, struct user_namespace *ns, int cap) +{ + if (unlikely(!cap_valid(cap))) { + printk(KERN_CRIT "capable() called with invalid cap=%u\n", cap); + BUG(); + } + + rcu_read_lock(); + if (security_task_capable(task, ns, __task_cred(task), cap) == 0) { + rcu_read_unlock(); + task->flags |= PF_SUPERPRIV; + return true; + } + rcu_read_unlock(); + return false; +} +EXPORT_SYMBOL(ns_task_capable); + /** * ns_capable - Determine if the current task has a superior capability in effect * @ns: The usernamespace we want the capability in @@ -369,16 +393,7 @@ EXPORT_SYMBOL(capable); */ bool ns_capable(struct user_namespace *ns, int cap) { - if (unlikely(!cap_valid(cap))) { - printk(KERN_CRIT "capable() called with invalid cap=%u\n", cap); - BUG(); - } - - if (security_capable(ns, current_cred(), cap) == 0) { - current->flags |= PF_SUPERPRIV; - return true; - } - return false; + return ns_task_capable(current, ns, cap); } EXPORT_SYMBOL(ns_capable); diff --git a/kernel/groups.c b/kernel/groups.c index 1cc476d..98ed200 100644 --- a/kernel/groups.c +++ b/kernel/groups.c @@ -268,6 +268,25 @@ int in_group_p(gid_t grp) EXPORT_SYMBOL(in_group_p); +/* + * Check whether task's fsgid/egid or in the supplemental group.. + */ +int task_in_group_p(struct task_struct *task, gid_t grp) +{ + const struct cred *cred; + int retval = 1; + + rcu_read_lock(); + cred = __task_cred(task); + + if (grp != cred->fsgid) + retval = groups_search(cred->group_info, grp); + rcu_read_unlock(); + return retval; +} + +EXPORT_SYMBOL(task_in_group_p); + int in_egroup_p(gid_t grp) { const struct cred *cred = current_cred(); diff --git a/kernel/pid.c b/kernel/pid.c index 57a8346..0f692ce 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -78,6 +78,7 @@ struct pid_namespace init_pid_ns = { .last_pid = 0, .level = 0, .child_reaper = &init_task, + .procinfo_restricted_gid = -1, }; EXPORT_SYMBOL_GPL(init_pid_ns); diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index e9c9adc..24b76c2 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -101,6 +101,8 @@ static struct pid_namespace *create_pid_namespace(struct pid_namespace *parent_p if (err) goto out_put_parent_pid_ns; + ns->procinfo_restricted_gid = -1; + return ns; out_put_parent_pid_ns: diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 2df1157..ccbec73 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -132,9 +132,9 @@ int ptrace_check_attach(struct task_struct *child, int kill) return ret; } -int __ptrace_may_access(struct task_struct *task, unsigned int mode) +int __ptrace_may_access(struct task_struct *who, struct task_struct *task, unsigned int mode) { - const struct cred *cred = current_cred(), *tcred; + const struct cred *cred, *tcred; /* May we inspect the given task? * This check is used both for attaching with ptrace @@ -146,9 +146,10 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode) */ int dumpable = 0; /* Don't let security modules deny introspection */ - if (task == current) + if (task == who) return 0; rcu_read_lock(); + cred = __task_cred(who); tcred = __task_cred(task); if (cred->user->user_ns == tcred->user->user_ns && (cred->uid == tcred->euid && @@ -158,7 +159,7 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode) cred->gid == tcred->sgid && cred->gid == tcred->gid)) goto ok; - if (ns_capable(tcred->user->user_ns, CAP_SYS_PTRACE)) + if (ns_task_capable(who, tcred->user->user_ns, CAP_SYS_PTRACE)) goto ok; rcu_read_unlock(); return -EPERM; @@ -167,17 +168,32 @@ ok: smp_rmb(); if (task->mm) dumpable = get_dumpable(task->mm); - if (!dumpable && !task_ns_capable(task, CAP_SYS_PTRACE)) + if (!dumpable && + !ns_task_capable(who, task_cred_xxx(task, user)->user_ns, + CAP_SYS_PTRACE)) return -EPERM; - return security_ptrace_access_check(task, mode); + return security_ptrace_task_access_check(who, task, mode); } bool ptrace_may_access(struct task_struct *task, unsigned int mode) { int err; task_lock(task); - err = __ptrace_may_access(task, mode); + err = __ptrace_may_access(current, task, mode); + task_unlock(task); + return !err; +} + +/* + * Generic task_may_access_task cannot be implemented because we have to + * hold task_locks of both tasks. It would lead to a deadlock. + */ +bool ptrace_task_may_access_current(struct task_struct *task, unsigned int mode) +{ + int err; + task_lock(task); + err = __ptrace_may_access(task, current, mode); task_unlock(task); return !err; } @@ -205,7 +221,7 @@ static int ptrace_attach(struct task_struct *task) goto out; task_lock(task); - retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH); + retval = __ptrace_may_access(current, task, PTRACE_MODE_ATTACH); task_unlock(task); if (retval) goto unlock_creds; diff --git a/kernel/sysctl.c b/kernel/sysctl.c index f175d98..da95aab 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -57,6 +57,7 @@ #include <linux/pipe_fs_i.h> #include <linux/oom.h> #include <linux/kmod.h> +#include <linux/pid_namespace.h> #include <asm/uaccess.h> #include <asm/processor.h> @@ -984,6 +985,22 @@ static struct ctl_table kern_table[] = { .proc_handler = proc_dointvec, }, #endif + { + .procname = "procinfo_restricted", + .data = &init_pid_ns.procinfo_restricted, + .maxlen = sizeof(init_pid_ns.procinfo_restricted), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &one, + }, + { + .procname = "procinfo_restricted_gid", + .data = &init_pid_ns.procinfo_restricted_gid, + .maxlen = sizeof(init_pid_ns.procinfo_restricted_gid), + .mode = 0644, + .proc_handler = proc_dointvec, + }, { } }; diff --git a/kernel/taskstats.c b/kernel/taskstats.c index 9ffea36..bec6258 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -27,6 +27,7 @@ #include <linux/cgroup.h> #include <linux/fs.h> #include <linux/file.h> +#include <linux/pid_namespace.h> #include <net/genetlink.h> #include <asm/atomic.h> @@ -132,6 +133,7 @@ static void send_cpu_listeners(struct sk_buff *skb, struct sk_buff *skb_next, *skb_cur = skb; void *reply = genlmsg_data(genlhdr); int rc, delcount = 0; + struct task_struct *tsk; rc = genlmsg_end(skb, reply); if (rc < 0) { @@ -143,6 +145,15 @@ static void send_cpu_listeners(struct sk_buff *skb, down_read(&listeners->sem); list_for_each_entry(s, &listeners->list, list) { skb_next = NULL; + + rcu_read_lock(); + tsk = find_task_by_vpid(s->pid); + if (!tsk || !procinfo_task_may_stat_current(tsk)) { + rcu_read_unlock(); + continue; + } + rcu_read_unlock(); + if (!list_is_last(&s->list, &listeners->list)) { skb_next = skb_clone(skb_cur, GFP_KERNEL); if (!skb_next) @@ -199,14 +210,20 @@ static void fill_stats(struct task_struct *tsk, struct taskstats *stats) static int fill_stats_for_pid(pid_t pid, struct taskstats *stats) { struct task_struct *tsk; + int err = -ESRCH; rcu_read_lock(); tsk = find_task_by_vpid(pid); + if (tsk && !procinfo_may_stat_task(tsk)) { + tsk = NULL; + err = -EACCES; + } + if (tsk) get_task_struct(tsk); rcu_read_unlock(); if (!tsk) - return -ESRCH; + return err; fill_stats(tsk, stats); put_task_struct(tsk); return 0; @@ -217,6 +234,7 @@ static int fill_stats_for_tgid(pid_t tgid, struct taskstats *stats) struct task_struct *tsk, *first; unsigned long flags; int rc = -ESRCH; + bool filled; /* * Add additional stats from live tasks except zombie thread group @@ -228,15 +246,29 @@ static int fill_stats_for_tgid(pid_t tgid, struct taskstats *stats) if (!first || !lock_task_sighand(first, &flags)) goto out; - if (first->signal->stats) + if (first->signal->stats && procinfo_may_stat_task(first)) { memcpy(stats, first->signal->stats, sizeof(*stats)); - else + filled = true; + } else { memset(stats, 0, sizeof(*stats)); + filled = false; + } tsk = first; do { if (tsk->exit_state) continue; + + /* + * As there could be tasks with different creds in the same + * process group, we should check perms for each task + * separately. + */ + if (!procinfo_may_stat_task(tsk)) + continue; + + filled = true; + /* * Accounting subsystem can call its functions here to * fill in relevant parts of struct taskstsats as follows @@ -250,7 +282,11 @@ static int fill_stats_for_tgid(pid_t tgid, struct taskstats *stats) } while_each_thread(first, tsk); unlock_task_sighand(first, &flags); - rc = 0; + + if (filled) + rc = 0; + else + rc = -EACCES; out: rcu_read_unlock(); diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index ec1bcec..dc3a4aa 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -93,14 +93,14 @@ static void apparmor_cred_transfer(struct cred *new, const struct cred *old) aa_dup_task_context(new_cxt, old_cxt); } -static int apparmor_ptrace_access_check(struct task_struct *child, - unsigned int mode) +static int apparmor_ptrace_access_check(struct task_struct *task, + struct task_struct *child, unsigned int mode) { - int error = cap_ptrace_access_check(child, mode); + int error = cap_ptrace_access_check(task, child, mode); if (error) return error; - return aa_ptrace(current, child, mode); + return aa_ptrace(task, child, mode); } static int apparmor_ptrace_traceme(struct task_struct *parent) diff --git a/security/commoncap.c b/security/commoncap.c index a93b3b7..31ca991 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -136,18 +136,19 @@ int cap_settime(const struct timespec *ts, const struct timezone *tz) * Determine whether a process may access another, returning 0 if permission * granted, -ve if denied. */ -int cap_ptrace_access_check(struct task_struct *child, unsigned int mode) +int cap_ptrace_access_check(struct task_struct *task, struct task_struct *child, + unsigned int mode) { int ret = 0; const struct cred *cred, *child_cred; rcu_read_lock(); - cred = current_cred(); + cred = __task_cred(task); child_cred = __task_cred(child); if (cred->user->user_ns == child_cred->user->user_ns && cap_issubset(child_cred->cap_permitted, cred->cap_permitted)) goto out; - if (ns_capable(child_cred->user->user_ns, CAP_SYS_PTRACE)) + if (ns_task_capable(task, child_cred->user->user_ns, CAP_SYS_PTRACE)) goto out; ret = -EPERM; out: diff --git a/security/security.c b/security/security.c index 4ba6d4c..0760e81 100644 --- a/security/security.c +++ b/security/security.c @@ -127,9 +127,15 @@ int __init register_security(struct security_operations *ops) /* Security operations */ +int security_ptrace_task_access_check(struct task_struct *task, + struct task_struct *child, unsigned int mode) +{ + return security_ops->ptrace_access_check(task, child, mode); +} + int security_ptrace_access_check(struct task_struct *child, unsigned int mode) { - return security_ops->ptrace_access_check(child, mode); + return security_ops->ptrace_access_check(current, child, mode); } int security_ptrace_traceme(struct task_struct *parent) @@ -154,11 +160,16 @@ int security_capset(struct cred *new, const struct cred *old, effective, inheritable, permitted); } +int security_task_capable(struct task_struct *task, struct user_namespace *ns, + const struct cred *cred, int cap) +{ + return security_ops->capable(task, cred, ns, cap, SECURITY_CAP_AUDIT); +} + int security_capable(struct user_namespace *ns, const struct cred *cred, int cap) { - return security_ops->capable(current, cred, ns, cap, - SECURITY_CAP_AUDIT); + return security_task_capable(current, ns, cred, cap); } int security_real_capable(struct task_struct *tsk, struct user_namespace *ns, diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 20219ef..0130255 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1804,23 +1804,22 @@ static inline u32 open_file_to_av(struct file *file) } /* Hook functions begin here. */ - -static int selinux_ptrace_access_check(struct task_struct *child, - unsigned int mode) +static int selinux_ptrace_access_check(struct task_struct *task, + struct task_struct *child, unsigned int mode) { int rc; - rc = cap_ptrace_access_check(child, mode); + rc = cap_ptrace_access_check(task, child, mode); if (rc) return rc; if (mode == PTRACE_MODE_READ) { - u32 sid = current_sid(); + u32 sid = task_sid(task); u32 csid = task_sid(child); return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL); } - return current_has_perm(child, PROCESS__PTRACE); + return task_has_perm(task, child, PROCESS__PTRACE); } static int selinux_ptrace_traceme(struct task_struct *parent) diff --git a/security/smack/smack.h b/security/smack/smack.h index 2b6c6a5..4d9fb0f 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -199,6 +199,7 @@ struct inode_smack *new_inode_smack(char *); */ int smk_access_entry(char *, char *, struct list_head *); int smk_access(char *, char *, int, struct smk_audit_info *); +int smk_taskacc(struct task_struct *, char *, u32, struct smk_audit_info *); int smk_curacc(char *, u32, struct smk_audit_info *); int smack_to_cipso(const char *, struct smack_cipso *); void smack_from_cipso(u32, char *, char *); diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index 9637e10..766dccd 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c @@ -201,7 +201,8 @@ out_audit: } /** - * smk_curacc - determine if current has a specific access to an object + * smk_curacc - determine if subject has a specific access to an object + * @task: a pointer to the subject's task struct * @obj_label: a pointer to the object's Smack label * @mode: the access requested, in "MAY" format * @a : common audit data @@ -211,9 +212,9 @@ out_audit: * non zero otherwise. It allows that current may have the capability * to override the rules. */ -int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) +int smk_taskacc(struct task_struct *task, char *obj_label, u32 mode, struct smk_audit_info *a) { - struct task_smack *tsp = current_security(); + struct task_smack *tsp = task_cred_xxx(task, security); char *sp = smk_of_task(tsp); int may; int rc; @@ -243,7 +244,7 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) if (smack_onlycap != NULL && smack_onlycap != sp) goto out_audit; - if (capable(CAP_MAC_OVERRIDE)) + if (task_capable(task, CAP_MAC_OVERRIDE)) rc = 0; out_audit: @@ -254,6 +255,22 @@ out_audit: return rc; } +/** + * smk_curacc - determine if current has a specific access to an object + * @obj_label: a pointer to the object's Smack label + * @mode: the access requested, in "MAY" format + * @a : common audit data + * + * This function checks the current subject label/object label pair + * in the access rule list and returns 0 if the access is permitted, + * non zero otherwise. It allows that current may have the capability + * to override the rules. + */ +int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) +{ + return smk_taskacc(current, obj_label, mode, a); +} + #ifdef CONFIG_AUDIT /** * smack_str_from_perm : helper to transalate an int to a diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 9831a39..ee1c5cb 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -149,13 +149,14 @@ static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead, * * Do the capability checks, and require read and write. */ -static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) +static int smack_ptrace_access_check(struct task_struct *task, + struct task_struct *ctp, unsigned int mode) { int rc; struct smk_audit_info ad; char *tsp; - rc = cap_ptrace_access_check(ctp, mode); + rc = cap_ptrace_access_check(task, ctp, mode); if (rc != 0) return rc; @@ -163,7 +164,7 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); smk_ad_setfield_u_tsk(&ad, ctp); - rc = smk_curacc(tsp, MAY_READWRITE, &ad); + rc = smk_taskacc(task, tsp, MAY_READWRITE, &ad); return rc; } -- Vasiliy Kulikov http://www.openwall.com - bringing security into open computing environments
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.