diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-19 12:21:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-19 12:21:36 -0400 |
commit | f4f27d0028aabce57e44c16c2fdefccd6310d2f3 (patch) | |
tree | 09f25601316d22b64165c19042da51c101bde3c4 /security/selinux/hooks.c | |
parent | 2600a46ee0ed57c0e0a382c2a37ebac64d374d20 (diff) | |
parent | b937190c40de0f6f07f592042e3097b16c6b0130 (diff) |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris:
"Highlights:
- A new LSM, "LoadPin", from Kees Cook is added, which allows forcing
of modules and firmware to be loaded from a specific device (this
is from ChromeOS, where the device as a whole is verified
cryptographically via dm-verity).
This is disabled by default but can be configured to be enabled by
default (don't do this if you don't know what you're doing).
- Keys: allow authentication data to be stored in an asymmetric key.
Lots of general fixes and updates.
- SELinux: add restrictions for loading of kernel modules via
finit_module(). Distinguish non-init user namespace capability
checks. Apply execstack check on thread stacks"
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (48 commits)
LSM: LoadPin: provide enablement CONFIG
Yama: use atomic allocations when reporting
seccomp: Fix comment typo
ima: add support for creating files using the mknodat syscall
ima: fix ima_inode_post_setattr
vfs: forbid write access when reading a file into memory
fs: fix over-zealous use of "const"
selinux: apply execstack check on thread stacks
selinux: distinguish non-init user namespace capability checks
LSM: LoadPin for kernel file loading restrictions
fs: define a string representation of the kernel_read_file_id enumeration
Yama: consolidate error reporting
string_helpers: add kstrdup_quotable_file
string_helpers: add kstrdup_quotable_cmdline
string_helpers: add kstrdup_quotable
selinux: check ss_initialized before revalidating an inode label
selinux: delay inode label lookup as long as possible
selinux: don't revalidate an inode's label when explicitly setting it
selinux: Change bool variable name to index.
KEYS: Add KEYCTL_DH_COMPUTE command
...
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 144 |
1 files changed, 102 insertions, 42 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3140efa76a75..a86d537eb79b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -259,7 +259,7 @@ static int __inode_security_revalidate(struct inode *inode, | |||
259 | 259 | ||
260 | might_sleep_if(may_sleep); | 260 | might_sleep_if(may_sleep); |
261 | 261 | ||
262 | if (isec->initialized == LABEL_INVALID) { | 262 | if (ss_initialized && isec->initialized != LABEL_INITIALIZED) { |
263 | if (!may_sleep) | 263 | if (!may_sleep) |
264 | return -ECHILD; | 264 | return -ECHILD; |
265 | 265 | ||
@@ -297,6 +297,13 @@ static struct inode_security_struct *inode_security(struct inode *inode) | |||
297 | return inode->i_security; | 297 | return inode->i_security; |
298 | } | 298 | } |
299 | 299 | ||
300 | static struct inode_security_struct *backing_inode_security_novalidate(struct dentry *dentry) | ||
301 | { | ||
302 | struct inode *inode = d_backing_inode(dentry); | ||
303 | |||
304 | return inode->i_security; | ||
305 | } | ||
306 | |||
300 | /* | 307 | /* |
301 | * Get the security label of a dentry's backing inode. | 308 | * Get the security label of a dentry's backing inode. |
302 | */ | 309 | */ |
@@ -687,7 +694,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
687 | struct superblock_security_struct *sbsec = sb->s_security; | 694 | struct superblock_security_struct *sbsec = sb->s_security; |
688 | const char *name = sb->s_type->name; | 695 | const char *name = sb->s_type->name; |
689 | struct dentry *root = sbsec->sb->s_root; | 696 | struct dentry *root = sbsec->sb->s_root; |
690 | struct inode_security_struct *root_isec = backing_inode_security(root); | 697 | struct inode_security_struct *root_isec; |
691 | u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; | 698 | u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; |
692 | u32 defcontext_sid = 0; | 699 | u32 defcontext_sid = 0; |
693 | char **mount_options = opts->mnt_opts; | 700 | char **mount_options = opts->mnt_opts; |
@@ -730,6 +737,8 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
730 | && (num_opts == 0)) | 737 | && (num_opts == 0)) |
731 | goto out; | 738 | goto out; |
732 | 739 | ||
740 | root_isec = backing_inode_security_novalidate(root); | ||
741 | |||
733 | /* | 742 | /* |
734 | * parse the mount options, check if they are valid sids. | 743 | * parse the mount options, check if they are valid sids. |
735 | * also check if someone is trying to mount the same sb more | 744 | * also check if someone is trying to mount the same sb more |
@@ -1623,7 +1632,7 @@ static int current_has_perm(const struct task_struct *tsk, | |||
1623 | 1632 | ||
1624 | /* Check whether a task is allowed to use a capability. */ | 1633 | /* Check whether a task is allowed to use a capability. */ |
1625 | static int cred_has_capability(const struct cred *cred, | 1634 | static int cred_has_capability(const struct cred *cred, |
1626 | int cap, int audit) | 1635 | int cap, int audit, bool initns) |
1627 | { | 1636 | { |
1628 | struct common_audit_data ad; | 1637 | struct common_audit_data ad; |
1629 | struct av_decision avd; | 1638 | struct av_decision avd; |
@@ -1637,10 +1646,10 @@ static int cred_has_capability(const struct cred *cred, | |||
1637 | 1646 | ||
1638 | switch (CAP_TO_INDEX(cap)) { | 1647 | switch (CAP_TO_INDEX(cap)) { |
1639 | case 0: | 1648 | case 0: |
1640 | sclass = SECCLASS_CAPABILITY; | 1649 | sclass = initns ? SECCLASS_CAPABILITY : SECCLASS_CAP_USERNS; |
1641 | break; | 1650 | break; |
1642 | case 1: | 1651 | case 1: |
1643 | sclass = SECCLASS_CAPABILITY2; | 1652 | sclass = initns ? SECCLASS_CAPABILITY2 : SECCLASS_CAP2_USERNS; |
1644 | break; | 1653 | break; |
1645 | default: | 1654 | default: |
1646 | printk(KERN_ERR | 1655 | printk(KERN_ERR |
@@ -1782,7 +1791,6 @@ static int selinux_determine_inode_label(struct inode *dir, | |||
1782 | u32 *_new_isid) | 1791 | u32 *_new_isid) |
1783 | { | 1792 | { |
1784 | const struct superblock_security_struct *sbsec = dir->i_sb->s_security; | 1793 | const struct superblock_security_struct *sbsec = dir->i_sb->s_security; |
1785 | const struct inode_security_struct *dsec = inode_security(dir); | ||
1786 | const struct task_security_struct *tsec = current_security(); | 1794 | const struct task_security_struct *tsec = current_security(); |
1787 | 1795 | ||
1788 | if ((sbsec->flags & SE_SBINITIALIZED) && | 1796 | if ((sbsec->flags & SE_SBINITIALIZED) && |
@@ -1792,6 +1800,7 @@ static int selinux_determine_inode_label(struct inode *dir, | |||
1792 | tsec->create_sid) { | 1800 | tsec->create_sid) { |
1793 | *_new_isid = tsec->create_sid; | 1801 | *_new_isid = tsec->create_sid; |
1794 | } else { | 1802 | } else { |
1803 | const struct inode_security_struct *dsec = inode_security(dir); | ||
1795 | return security_transition_sid(tsec->sid, dsec->sid, tclass, | 1804 | return security_transition_sid(tsec->sid, dsec->sid, tclass, |
1796 | name, _new_isid); | 1805 | name, _new_isid); |
1797 | } | 1806 | } |
@@ -2076,7 +2085,7 @@ static int selinux_binder_transfer_file(struct task_struct *from, | |||
2076 | u32 sid = task_sid(to); | 2085 | u32 sid = task_sid(to); |
2077 | struct file_security_struct *fsec = file->f_security; | 2086 | struct file_security_struct *fsec = file->f_security; |
2078 | struct dentry *dentry = file->f_path.dentry; | 2087 | struct dentry *dentry = file->f_path.dentry; |
2079 | struct inode_security_struct *isec = backing_inode_security(dentry); | 2088 | struct inode_security_struct *isec; |
2080 | struct common_audit_data ad; | 2089 | struct common_audit_data ad; |
2081 | int rc; | 2090 | int rc; |
2082 | 2091 | ||
@@ -2095,6 +2104,7 @@ static int selinux_binder_transfer_file(struct task_struct *from, | |||
2095 | if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) | 2104 | if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) |
2096 | return 0; | 2105 | return 0; |
2097 | 2106 | ||
2107 | isec = backing_inode_security(dentry); | ||
2098 | return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file), | 2108 | return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file), |
2099 | &ad); | 2109 | &ad); |
2100 | } | 2110 | } |
@@ -2143,7 +2153,7 @@ static int selinux_capset(struct cred *new, const struct cred *old, | |||
2143 | static int selinux_capable(const struct cred *cred, struct user_namespace *ns, | 2153 | static int selinux_capable(const struct cred *cred, struct user_namespace *ns, |
2144 | int cap, int audit) | 2154 | int cap, int audit) |
2145 | { | 2155 | { |
2146 | return cred_has_capability(cred, cap, audit); | 2156 | return cred_has_capability(cred, cap, audit, ns == &init_user_ns); |
2147 | } | 2157 | } |
2148 | 2158 | ||
2149 | static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb) | 2159 | static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb) |
@@ -2221,7 +2231,7 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages) | |||
2221 | int rc, cap_sys_admin = 0; | 2231 | int rc, cap_sys_admin = 0; |
2222 | 2232 | ||
2223 | rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN, | 2233 | rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN, |
2224 | SECURITY_CAP_NOAUDIT); | 2234 | SECURITY_CAP_NOAUDIT, true); |
2225 | if (rc == 0) | 2235 | if (rc == 0) |
2226 | cap_sys_admin = 1; | 2236 | cap_sys_admin = 1; |
2227 | 2237 | ||
@@ -2230,6 +2240,20 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages) | |||
2230 | 2240 | ||
2231 | /* binprm security operations */ | 2241 | /* binprm security operations */ |
2232 | 2242 | ||
2243 | static u32 ptrace_parent_sid(struct task_struct *task) | ||
2244 | { | ||
2245 | u32 sid = 0; | ||
2246 | struct task_struct *tracer; | ||
2247 | |||
2248 | rcu_read_lock(); | ||
2249 | tracer = ptrace_parent(task); | ||
2250 | if (tracer) | ||
2251 | sid = task_sid(tracer); | ||
2252 | rcu_read_unlock(); | ||
2253 | |||
2254 | return sid; | ||
2255 | } | ||
2256 | |||
2233 | static int check_nnp_nosuid(const struct linux_binprm *bprm, | 2257 | static int check_nnp_nosuid(const struct linux_binprm *bprm, |
2234 | const struct task_security_struct *old_tsec, | 2258 | const struct task_security_struct *old_tsec, |
2235 | const struct task_security_struct *new_tsec) | 2259 | const struct task_security_struct *new_tsec) |
@@ -2351,18 +2375,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2351 | * changes its SID has the appropriate permit */ | 2375 | * changes its SID has the appropriate permit */ |
2352 | if (bprm->unsafe & | 2376 | if (bprm->unsafe & |
2353 | (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { | 2377 | (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { |
2354 | struct task_struct *tracer; | 2378 | u32 ptsid = ptrace_parent_sid(current); |
2355 | struct task_security_struct *sec; | ||
2356 | u32 ptsid = 0; | ||
2357 | |||
2358 | rcu_read_lock(); | ||
2359 | tracer = ptrace_parent(current); | ||
2360 | if (likely(tracer != NULL)) { | ||
2361 | sec = __task_cred(tracer)->security; | ||
2362 | ptsid = sec->sid; | ||
2363 | } | ||
2364 | rcu_read_unlock(); | ||
2365 | |||
2366 | if (ptsid != 0) { | 2379 | if (ptsid != 0) { |
2367 | rc = avc_has_perm(ptsid, new_tsec->sid, | 2380 | rc = avc_has_perm(ptsid, new_tsec->sid, |
2368 | SECCLASS_PROCESS, | 2381 | SECCLASS_PROCESS, |
@@ -3046,7 +3059,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
3046 | const void *value, size_t size, int flags) | 3059 | const void *value, size_t size, int flags) |
3047 | { | 3060 | { |
3048 | struct inode *inode = d_backing_inode(dentry); | 3061 | struct inode *inode = d_backing_inode(dentry); |
3049 | struct inode_security_struct *isec = backing_inode_security(dentry); | 3062 | struct inode_security_struct *isec; |
3050 | struct superblock_security_struct *sbsec; | 3063 | struct superblock_security_struct *sbsec; |
3051 | struct common_audit_data ad; | 3064 | struct common_audit_data ad; |
3052 | u32 newsid, sid = current_sid(); | 3065 | u32 newsid, sid = current_sid(); |
@@ -3065,6 +3078,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
3065 | ad.type = LSM_AUDIT_DATA_DENTRY; | 3078 | ad.type = LSM_AUDIT_DATA_DENTRY; |
3066 | ad.u.dentry = dentry; | 3079 | ad.u.dentry = dentry; |
3067 | 3080 | ||
3081 | isec = backing_inode_security(dentry); | ||
3068 | rc = avc_has_perm(sid, isec->sid, isec->sclass, | 3082 | rc = avc_has_perm(sid, isec->sid, isec->sclass, |
3069 | FILE__RELABELFROM, &ad); | 3083 | FILE__RELABELFROM, &ad); |
3070 | if (rc) | 3084 | if (rc) |
@@ -3123,7 +3137,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
3123 | int flags) | 3137 | int flags) |
3124 | { | 3138 | { |
3125 | struct inode *inode = d_backing_inode(dentry); | 3139 | struct inode *inode = d_backing_inode(dentry); |
3126 | struct inode_security_struct *isec = backing_inode_security(dentry); | 3140 | struct inode_security_struct *isec; |
3127 | u32 newsid; | 3141 | u32 newsid; |
3128 | int rc; | 3142 | int rc; |
3129 | 3143 | ||
@@ -3140,6 +3154,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
3140 | return; | 3154 | return; |
3141 | } | 3155 | } |
3142 | 3156 | ||
3157 | isec = backing_inode_security(dentry); | ||
3143 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | 3158 | isec->sclass = inode_mode_to_security_class(inode->i_mode); |
3144 | isec->sid = newsid; | 3159 | isec->sid = newsid; |
3145 | isec->initialized = LABEL_INITIALIZED; | 3160 | isec->initialized = LABEL_INITIALIZED; |
@@ -3181,7 +3196,7 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void | |||
3181 | u32 size; | 3196 | u32 size; |
3182 | int error; | 3197 | int error; |
3183 | char *context = NULL; | 3198 | char *context = NULL; |
3184 | struct inode_security_struct *isec = inode_security(inode); | 3199 | struct inode_security_struct *isec; |
3185 | 3200 | ||
3186 | if (strcmp(name, XATTR_SELINUX_SUFFIX)) | 3201 | if (strcmp(name, XATTR_SELINUX_SUFFIX)) |
3187 | return -EOPNOTSUPP; | 3202 | return -EOPNOTSUPP; |
@@ -3199,7 +3214,8 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void | |||
3199 | SECURITY_CAP_NOAUDIT); | 3214 | SECURITY_CAP_NOAUDIT); |
3200 | if (!error) | 3215 | if (!error) |
3201 | error = cred_has_capability(current_cred(), CAP_MAC_ADMIN, | 3216 | error = cred_has_capability(current_cred(), CAP_MAC_ADMIN, |
3202 | SECURITY_CAP_NOAUDIT); | 3217 | SECURITY_CAP_NOAUDIT, true); |
3218 | isec = inode_security(inode); | ||
3203 | if (!error) | 3219 | if (!error) |
3204 | error = security_sid_to_context_force(isec->sid, &context, | 3220 | error = security_sid_to_context_force(isec->sid, &context, |
3205 | &size); | 3221 | &size); |
@@ -3220,7 +3236,7 @@ out_nofree: | |||
3220 | static int selinux_inode_setsecurity(struct inode *inode, const char *name, | 3236 | static int selinux_inode_setsecurity(struct inode *inode, const char *name, |
3221 | const void *value, size_t size, int flags) | 3237 | const void *value, size_t size, int flags) |
3222 | { | 3238 | { |
3223 | struct inode_security_struct *isec = inode_security(inode); | 3239 | struct inode_security_struct *isec = inode_security_novalidate(inode); |
3224 | u32 newsid; | 3240 | u32 newsid; |
3225 | int rc; | 3241 | int rc; |
3226 | 3242 | ||
@@ -3309,7 +3325,7 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file, | |||
3309 | struct common_audit_data ad; | 3325 | struct common_audit_data ad; |
3310 | struct file_security_struct *fsec = file->f_security; | 3326 | struct file_security_struct *fsec = file->f_security; |
3311 | struct inode *inode = file_inode(file); | 3327 | struct inode *inode = file_inode(file); |
3312 | struct inode_security_struct *isec = inode_security(inode); | 3328 | struct inode_security_struct *isec; |
3313 | struct lsm_ioctlop_audit ioctl; | 3329 | struct lsm_ioctlop_audit ioctl; |
3314 | u32 ssid = cred_sid(cred); | 3330 | u32 ssid = cred_sid(cred); |
3315 | int rc; | 3331 | int rc; |
@@ -3333,6 +3349,7 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file, | |||
3333 | if (unlikely(IS_PRIVATE(inode))) | 3349 | if (unlikely(IS_PRIVATE(inode))) |
3334 | return 0; | 3350 | return 0; |
3335 | 3351 | ||
3352 | isec = inode_security(inode); | ||
3336 | rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass, | 3353 | rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass, |
3337 | requested, driver, xperm, &ad); | 3354 | requested, driver, xperm, &ad); |
3338 | out: | 3355 | out: |
@@ -3374,7 +3391,7 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, | |||
3374 | case KDSKBENT: | 3391 | case KDSKBENT: |
3375 | case KDSKBSENT: | 3392 | case KDSKBSENT: |
3376 | error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG, | 3393 | error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG, |
3377 | SECURITY_CAP_AUDIT); | 3394 | SECURITY_CAP_AUDIT, true); |
3378 | break; | 3395 | break; |
3379 | 3396 | ||
3380 | /* default case assumes that the command will go | 3397 | /* default case assumes that the command will go |
@@ -3463,8 +3480,9 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
3463 | vma->vm_end <= vma->vm_mm->brk) { | 3480 | vma->vm_end <= vma->vm_mm->brk) { |
3464 | rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP); | 3481 | rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP); |
3465 | } else if (!vma->vm_file && | 3482 | } else if (!vma->vm_file && |
3466 | vma->vm_start <= vma->vm_mm->start_stack && | 3483 | ((vma->vm_start <= vma->vm_mm->start_stack && |
3467 | vma->vm_end >= vma->vm_mm->start_stack) { | 3484 | vma->vm_end >= vma->vm_mm->start_stack) || |
3485 | vma_is_stack_for_task(vma, current))) { | ||
3468 | rc = current_has_perm(current, PROCESS__EXECSTACK); | 3486 | rc = current_has_perm(current, PROCESS__EXECSTACK); |
3469 | } else if (vma->vm_file && vma->anon_vma) { | 3487 | } else if (vma->vm_file && vma->anon_vma) { |
3470 | /* | 3488 | /* |
@@ -3720,6 +3738,52 @@ static int selinux_kernel_module_request(char *kmod_name) | |||
3720 | SYSTEM__MODULE_REQUEST, &ad); | 3738 | SYSTEM__MODULE_REQUEST, &ad); |
3721 | } | 3739 | } |
3722 | 3740 | ||
3741 | static int selinux_kernel_module_from_file(struct file *file) | ||
3742 | { | ||
3743 | struct common_audit_data ad; | ||
3744 | struct inode_security_struct *isec; | ||
3745 | struct file_security_struct *fsec; | ||
3746 | u32 sid = current_sid(); | ||
3747 | int rc; | ||
3748 | |||
3749 | /* init_module */ | ||
3750 | if (file == NULL) | ||
3751 | return avc_has_perm(sid, sid, SECCLASS_SYSTEM, | ||
3752 | SYSTEM__MODULE_LOAD, NULL); | ||
3753 | |||
3754 | /* finit_module */ | ||
3755 | |||
3756 | ad.type = LSM_AUDIT_DATA_PATH; | ||
3757 | ad.u.path = file->f_path; | ||
3758 | |||
3759 | fsec = file->f_security; | ||
3760 | if (sid != fsec->sid) { | ||
3761 | rc = avc_has_perm(sid, fsec->sid, SECCLASS_FD, FD__USE, &ad); | ||
3762 | if (rc) | ||
3763 | return rc; | ||
3764 | } | ||
3765 | |||
3766 | isec = inode_security(file_inode(file)); | ||
3767 | return avc_has_perm(sid, isec->sid, SECCLASS_SYSTEM, | ||
3768 | SYSTEM__MODULE_LOAD, &ad); | ||
3769 | } | ||
3770 | |||
3771 | static int selinux_kernel_read_file(struct file *file, | ||
3772 | enum kernel_read_file_id id) | ||
3773 | { | ||
3774 | int rc = 0; | ||
3775 | |||
3776 | switch (id) { | ||
3777 | case READING_MODULE: | ||
3778 | rc = selinux_kernel_module_from_file(file); | ||
3779 | break; | ||
3780 | default: | ||
3781 | break; | ||
3782 | } | ||
3783 | |||
3784 | return rc; | ||
3785 | } | ||
3786 | |||
3723 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) | 3787 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) |
3724 | { | 3788 | { |
3725 | return current_has_perm(p, PROCESS__SETPGID); | 3789 | return current_has_perm(p, PROCESS__SETPGID); |
@@ -4599,6 +4663,7 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff * | |||
4599 | { | 4663 | { |
4600 | u32 peer_secid = SECSID_NULL; | 4664 | u32 peer_secid = SECSID_NULL; |
4601 | u16 family; | 4665 | u16 family; |
4666 | struct inode_security_struct *isec; | ||
4602 | 4667 | ||
4603 | if (skb && skb->protocol == htons(ETH_P_IP)) | 4668 | if (skb && skb->protocol == htons(ETH_P_IP)) |
4604 | family = PF_INET; | 4669 | family = PF_INET; |
@@ -4609,9 +4674,10 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff * | |||
4609 | else | 4674 | else |
4610 | goto out; | 4675 | goto out; |
4611 | 4676 | ||
4612 | if (sock && family == PF_UNIX) | 4677 | if (sock && family == PF_UNIX) { |
4613 | selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid); | 4678 | isec = inode_security_novalidate(SOCK_INODE(sock)); |
4614 | else if (skb) | 4679 | peer_secid = isec->sid; |
4680 | } else if (skb) | ||
4615 | selinux_skb_peerlbl_sid(skb, family, &peer_secid); | 4681 | selinux_skb_peerlbl_sid(skb, family, &peer_secid); |
4616 | 4682 | ||
4617 | out: | 4683 | out: |
@@ -5676,7 +5742,6 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5676 | char *name, void *value, size_t size) | 5742 | char *name, void *value, size_t size) |
5677 | { | 5743 | { |
5678 | struct task_security_struct *tsec; | 5744 | struct task_security_struct *tsec; |
5679 | struct task_struct *tracer; | ||
5680 | struct cred *new; | 5745 | struct cred *new; |
5681 | u32 sid = 0, ptsid; | 5746 | u32 sid = 0, ptsid; |
5682 | int error; | 5747 | int error; |
@@ -5783,14 +5848,8 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5783 | 5848 | ||
5784 | /* Check for ptracing, and update the task SID if ok. | 5849 | /* Check for ptracing, and update the task SID if ok. |
5785 | Otherwise, leave SID unchanged and fail. */ | 5850 | Otherwise, leave SID unchanged and fail. */ |
5786 | ptsid = 0; | 5851 | ptsid = ptrace_parent_sid(p); |
5787 | rcu_read_lock(); | 5852 | if (ptsid != 0) { |
5788 | tracer = ptrace_parent(p); | ||
5789 | if (tracer) | ||
5790 | ptsid = task_sid(tracer); | ||
5791 | rcu_read_unlock(); | ||
5792 | |||
5793 | if (tracer) { | ||
5794 | error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS, | 5853 | error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS, |
5795 | PROCESS__PTRACE, NULL); | 5854 | PROCESS__PTRACE, NULL); |
5796 | if (error) | 5855 | if (error) |
@@ -6021,6 +6080,7 @@ static struct security_hook_list selinux_hooks[] = { | |||
6021 | LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as), | 6080 | LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as), |
6022 | LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as), | 6081 | LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as), |
6023 | LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request), | 6082 | LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request), |
6083 | LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file), | ||
6024 | LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid), | 6084 | LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid), |
6025 | LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid), | 6085 | LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid), |
6026 | LSM_HOOK_INIT(task_getsid, selinux_task_getsid), | 6086 | LSM_HOOK_INIT(task_getsid, selinux_task_getsid), |