Skip to content

Commit a6926cc

Browse files
author
James Morris
committed
Merge branch 'stable-4.7' of git://git.infradead.org/users/pcmoore/selinux into next
2 parents 0250abc + c2316db commit a6926cc

File tree

6 files changed

+128
-61
lines changed

6 files changed

+128
-61
lines changed

net/netlabel/netlabel_kapi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,7 @@ int netlbl_catmap_setrng(struct netlbl_lsm_catmap **catmap,
677677
u32 spot = start;
678678

679679
while (rc == 0 && spot <= end) {
680-
if (((spot & (BITS_PER_LONG - 1)) != 0) &&
680+
if (((spot & (BITS_PER_LONG - 1)) == 0) &&
681681
((end - spot) > BITS_PER_LONG)) {
682682
rc = netlbl_catmap_setlong(catmap,
683683
spot,

security/selinux/hooks.c

Lines changed: 102 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ static int __inode_security_revalidate(struct inode *inode,
259259

260260
might_sleep_if(may_sleep);
261261

262-
if (isec->initialized == LABEL_INVALID) {
262+
if (ss_initialized && isec->initialized != LABEL_INITIALIZED) {
263263
if (!may_sleep)
264264
return -ECHILD;
265265

@@ -297,6 +297,13 @@ static struct inode_security_struct *inode_security(struct inode *inode)
297297
return inode->i_security;
298298
}
299299

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+
300307
/*
301308
* Get the security label of a dentry's backing inode.
302309
*/
@@ -686,7 +693,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
686693
struct superblock_security_struct *sbsec = sb->s_security;
687694
const char *name = sb->s_type->name;
688695
struct dentry *root = sbsec->sb->s_root;
689-
struct inode_security_struct *root_isec = backing_inode_security(root);
696+
struct inode_security_struct *root_isec;
690697
u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
691698
u32 defcontext_sid = 0;
692699
char **mount_options = opts->mnt_opts;
@@ -729,6 +736,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
729736
&& (num_opts == 0))
730737
goto out;
731738

739+
root_isec = backing_inode_security_novalidate(root);
740+
732741
/*
733742
* parse the mount options, check if they are valid sids.
734743
* also check if someone is trying to mount the same sb more
@@ -1622,7 +1631,7 @@ static int current_has_perm(const struct task_struct *tsk,
16221631

16231632
/* Check whether a task is allowed to use a capability. */
16241633
static int cred_has_capability(const struct cred *cred,
1625-
int cap, int audit)
1634+
int cap, int audit, bool initns)
16261635
{
16271636
struct common_audit_data ad;
16281637
struct av_decision avd;
@@ -1636,10 +1645,10 @@ static int cred_has_capability(const struct cred *cred,
16361645

16371646
switch (CAP_TO_INDEX(cap)) {
16381647
case 0:
1639-
sclass = SECCLASS_CAPABILITY;
1648+
sclass = initns ? SECCLASS_CAPABILITY : SECCLASS_CAP_USERNS;
16401649
break;
16411650
case 1:
1642-
sclass = SECCLASS_CAPABILITY2;
1651+
sclass = initns ? SECCLASS_CAPABILITY2 : SECCLASS_CAP2_USERNS;
16431652
break;
16441653
default:
16451654
printk(KERN_ERR
@@ -1781,7 +1790,6 @@ static int selinux_determine_inode_label(struct inode *dir,
17811790
u32 *_new_isid)
17821791
{
17831792
const struct superblock_security_struct *sbsec = dir->i_sb->s_security;
1784-
const struct inode_security_struct *dsec = inode_security(dir);
17851793
const struct task_security_struct *tsec = current_security();
17861794

17871795
if ((sbsec->flags & SE_SBINITIALIZED) &&
@@ -1791,6 +1799,7 @@ static int selinux_determine_inode_label(struct inode *dir,
17911799
tsec->create_sid) {
17921800
*_new_isid = tsec->create_sid;
17931801
} else {
1802+
const struct inode_security_struct *dsec = inode_security(dir);
17941803
return security_transition_sid(tsec->sid, dsec->sid, tclass,
17951804
name, _new_isid);
17961805
}
@@ -2075,7 +2084,7 @@ static int selinux_binder_transfer_file(struct task_struct *from,
20752084
u32 sid = task_sid(to);
20762085
struct file_security_struct *fsec = file->f_security;
20772086
struct dentry *dentry = file->f_path.dentry;
2078-
struct inode_security_struct *isec = backing_inode_security(dentry);
2087+
struct inode_security_struct *isec;
20792088
struct common_audit_data ad;
20802089
int rc;
20812090

@@ -2094,6 +2103,7 @@ static int selinux_binder_transfer_file(struct task_struct *from,
20942103
if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
20952104
return 0;
20962105

2106+
isec = backing_inode_security(dentry);
20972107
return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file),
20982108
&ad);
20992109
}
@@ -2142,7 +2152,7 @@ static int selinux_capset(struct cred *new, const struct cred *old,
21422152
static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
21432153
int cap, int audit)
21442154
{
2145-
return cred_has_capability(cred, cap, audit);
2155+
return cred_has_capability(cred, cap, audit, ns == &init_user_ns);
21462156
}
21472157

21482158
static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
@@ -2220,7 +2230,7 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
22202230
int rc, cap_sys_admin = 0;
22212231

22222232
rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
2223-
SECURITY_CAP_NOAUDIT);
2233+
SECURITY_CAP_NOAUDIT, true);
22242234
if (rc == 0)
22252235
cap_sys_admin = 1;
22262236

@@ -2229,6 +2239,20 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
22292239

22302240
/* binprm security operations */
22312241

2242+
static u32 ptrace_parent_sid(struct task_struct *task)
2243+
{
2244+
u32 sid = 0;
2245+
struct task_struct *tracer;
2246+
2247+
rcu_read_lock();
2248+
tracer = ptrace_parent(task);
2249+
if (tracer)
2250+
sid = task_sid(tracer);
2251+
rcu_read_unlock();
2252+
2253+
return sid;
2254+
}
2255+
22322256
static int check_nnp_nosuid(const struct linux_binprm *bprm,
22332257
const struct task_security_struct *old_tsec,
22342258
const struct task_security_struct *new_tsec)
@@ -2350,18 +2374,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
23502374
* changes its SID has the appropriate permit */
23512375
if (bprm->unsafe &
23522376
(LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2353-
struct task_struct *tracer;
2354-
struct task_security_struct *sec;
2355-
u32 ptsid = 0;
2356-
2357-
rcu_read_lock();
2358-
tracer = ptrace_parent(current);
2359-
if (likely(tracer != NULL)) {
2360-
sec = __task_cred(tracer)->security;
2361-
ptsid = sec->sid;
2362-
}
2363-
rcu_read_unlock();
2364-
2377+
u32 ptsid = ptrace_parent_sid(current);
23652378
if (ptsid != 0) {
23662379
rc = avc_has_perm(ptsid, new_tsec->sid,
23672380
SECCLASS_PROCESS,
@@ -3045,7 +3058,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
30453058
const void *value, size_t size, int flags)
30463059
{
30473060
struct inode *inode = d_backing_inode(dentry);
3048-
struct inode_security_struct *isec = backing_inode_security(dentry);
3061+
struct inode_security_struct *isec;
30493062
struct superblock_security_struct *sbsec;
30503063
struct common_audit_data ad;
30513064
u32 newsid, sid = current_sid();
@@ -3064,6 +3077,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
30643077
ad.type = LSM_AUDIT_DATA_DENTRY;
30653078
ad.u.dentry = dentry;
30663079

3080+
isec = backing_inode_security(dentry);
30673081
rc = avc_has_perm(sid, isec->sid, isec->sclass,
30683082
FILE__RELABELFROM, &ad);
30693083
if (rc)
@@ -3122,7 +3136,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
31223136
int flags)
31233137
{
31243138
struct inode *inode = d_backing_inode(dentry);
3125-
struct inode_security_struct *isec = backing_inode_security(dentry);
3139+
struct inode_security_struct *isec;
31263140
u32 newsid;
31273141
int rc;
31283142

@@ -3139,6 +3153,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
31393153
return;
31403154
}
31413155

3156+
isec = backing_inode_security(dentry);
31423157
isec->sclass = inode_mode_to_security_class(inode->i_mode);
31433158
isec->sid = newsid;
31443159
isec->initialized = LABEL_INITIALIZED;
@@ -3180,7 +3195,7 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void
31803195
u32 size;
31813196
int error;
31823197
char *context = NULL;
3183-
struct inode_security_struct *isec = inode_security(inode);
3198+
struct inode_security_struct *isec;
31843199

31853200
if (strcmp(name, XATTR_SELINUX_SUFFIX))
31863201
return -EOPNOTSUPP;
@@ -3198,7 +3213,8 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void
31983213
SECURITY_CAP_NOAUDIT);
31993214
if (!error)
32003215
error = cred_has_capability(current_cred(), CAP_MAC_ADMIN,
3201-
SECURITY_CAP_NOAUDIT);
3216+
SECURITY_CAP_NOAUDIT, true);
3217+
isec = inode_security(inode);
32023218
if (!error)
32033219
error = security_sid_to_context_force(isec->sid, &context,
32043220
&size);
@@ -3219,7 +3235,7 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void
32193235
static int selinux_inode_setsecurity(struct inode *inode, const char *name,
32203236
const void *value, size_t size, int flags)
32213237
{
3222-
struct inode_security_struct *isec = inode_security(inode);
3238+
struct inode_security_struct *isec = inode_security_novalidate(inode);
32233239
u32 newsid;
32243240
int rc;
32253241

@@ -3308,7 +3324,7 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file,
33083324
struct common_audit_data ad;
33093325
struct file_security_struct *fsec = file->f_security;
33103326
struct inode *inode = file_inode(file);
3311-
struct inode_security_struct *isec = inode_security(inode);
3327+
struct inode_security_struct *isec;
33123328
struct lsm_ioctlop_audit ioctl;
33133329
u32 ssid = cred_sid(cred);
33143330
int rc;
@@ -3332,6 +3348,7 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file,
33323348
if (unlikely(IS_PRIVATE(inode)))
33333349
return 0;
33343350

3351+
isec = inode_security(inode);
33353352
rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass,
33363353
requested, driver, xperm, &ad);
33373354
out:
@@ -3373,7 +3390,7 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
33733390
case KDSKBENT:
33743391
case KDSKBSENT:
33753392
error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
3376-
SECURITY_CAP_AUDIT);
3393+
SECURITY_CAP_AUDIT, true);
33773394
break;
33783395

33793396
/* default case assumes that the command will go
@@ -3462,8 +3479,9 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
34623479
vma->vm_end <= vma->vm_mm->brk) {
34633480
rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
34643481
} else if (!vma->vm_file &&
3465-
vma->vm_start <= vma->vm_mm->start_stack &&
3466-
vma->vm_end >= vma->vm_mm->start_stack) {
3482+
((vma->vm_start <= vma->vm_mm->start_stack &&
3483+
vma->vm_end >= vma->vm_mm->start_stack) ||
3484+
vma_is_stack_for_task(vma, current))) {
34673485
rc = current_has_perm(current, PROCESS__EXECSTACK);
34683486
} else if (vma->vm_file && vma->anon_vma) {
34693487
/*
@@ -3719,6 +3737,52 @@ static int selinux_kernel_module_request(char *kmod_name)
37193737
SYSTEM__MODULE_REQUEST, &ad);
37203738
}
37213739

3740+
static int selinux_kernel_module_from_file(struct file *file)
3741+
{
3742+
struct common_audit_data ad;
3743+
struct inode_security_struct *isec;
3744+
struct file_security_struct *fsec;
3745+
u32 sid = current_sid();
3746+
int rc;
3747+
3748+
/* init_module */
3749+
if (file == NULL)
3750+
return avc_has_perm(sid, sid, SECCLASS_SYSTEM,
3751+
SYSTEM__MODULE_LOAD, NULL);
3752+
3753+
/* finit_module */
3754+
3755+
ad.type = LSM_AUDIT_DATA_PATH;
3756+
ad.u.path = file->f_path;
3757+
3758+
fsec = file->f_security;
3759+
if (sid != fsec->sid) {
3760+
rc = avc_has_perm(sid, fsec->sid, SECCLASS_FD, FD__USE, &ad);
3761+
if (rc)
3762+
return rc;
3763+
}
3764+
3765+
isec = inode_security(file_inode(file));
3766+
return avc_has_perm(sid, isec->sid, SECCLASS_SYSTEM,
3767+
SYSTEM__MODULE_LOAD, &ad);
3768+
}
3769+
3770+
static int selinux_kernel_read_file(struct file *file,
3771+
enum kernel_read_file_id id)
3772+
{
3773+
int rc = 0;
3774+
3775+
switch (id) {
3776+
case READING_MODULE:
3777+
rc = selinux_kernel_module_from_file(file);
3778+
break;
3779+
default:
3780+
break;
3781+
}
3782+
3783+
return rc;
3784+
}
3785+
37223786
static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
37233787
{
37243788
return current_has_perm(p, PROCESS__SETPGID);
@@ -4598,6 +4662,7 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
45984662
{
45994663
u32 peer_secid = SECSID_NULL;
46004664
u16 family;
4665+
struct inode_security_struct *isec;
46014666

46024667
if (skb && skb->protocol == htons(ETH_P_IP))
46034668
family = PF_INET;
@@ -4608,9 +4673,10 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
46084673
else
46094674
goto out;
46104675

4611-
if (sock && family == PF_UNIX)
4612-
selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
4613-
else if (skb)
4676+
if (sock && family == PF_UNIX) {
4677+
isec = inode_security_novalidate(SOCK_INODE(sock));
4678+
peer_secid = isec->sid;
4679+
} else if (skb)
46144680
selinux_skb_peerlbl_sid(skb, family, &peer_secid);
46154681

46164682
out:
@@ -5675,7 +5741,6 @@ static int selinux_setprocattr(struct task_struct *p,
56755741
char *name, void *value, size_t size)
56765742
{
56775743
struct task_security_struct *tsec;
5678-
struct task_struct *tracer;
56795744
struct cred *new;
56805745
u32 sid = 0, ptsid;
56815746
int error;
@@ -5782,14 +5847,8 @@ static int selinux_setprocattr(struct task_struct *p,
57825847

57835848
/* Check for ptracing, and update the task SID if ok.
57845849
Otherwise, leave SID unchanged and fail. */
5785-
ptsid = 0;
5786-
rcu_read_lock();
5787-
tracer = ptrace_parent(p);
5788-
if (tracer)
5789-
ptsid = task_sid(tracer);
5790-
rcu_read_unlock();
5791-
5792-
if (tracer) {
5850+
ptsid = ptrace_parent_sid(p);
5851+
if (ptsid != 0) {
57935852
error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
57945853
PROCESS__PTRACE, NULL);
57955854
if (error)
@@ -6020,6 +6079,7 @@ static struct security_hook_list selinux_hooks[] = {
60206079
LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
60216080
LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
60226081
LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
6082+
LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file),
60236083
LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
60246084
LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
60256085
LSM_HOOK_INIT(task_getsid, selinux_task_getsid),

0 commit comments

Comments
 (0)