diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/keys/key.c | 33 | ||||
-rw-r--r-- | security/selinux/hooks.c | 33 | ||||
-rw-r--r-- | security/selinux/include/xfrm.h | 9 | ||||
-rw-r--r-- | security/selinux/selinuxfs.c | 8 | ||||
-rw-r--r-- | security/selinux/ss/context.h | 23 | ||||
-rw-r--r-- | security/selinux/ss/mls.c | 30 | ||||
-rw-r--r-- | security/selinux/ss/mls.h | 20 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 16 |
8 files changed, 83 insertions, 89 deletions
diff --git a/security/keys/key.c b/security/keys/key.c index ac9326c5f1d..700400d801d 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -188,6 +188,7 @@ static inline void key_alloc_serial(struct key *key) spin_lock(&key_serial_lock); +attempt_insertion: parent = NULL; p = &key_serial_tree.rb_node; @@ -202,39 +203,33 @@ static inline void key_alloc_serial(struct key *key) else goto serial_exists; } - goto insert_here; + + /* we've found a suitable hole - arrange for this key to occupy it */ + rb_link_node(&key->serial_node, parent, p); + rb_insert_color(&key->serial_node, &key_serial_tree); + + spin_unlock(&key_serial_lock); + return; /* we found a key with the proposed serial number - walk the tree from * that point looking for the next unused serial number */ serial_exists: for (;;) { key->serial++; - if (key->serial < 2) - key->serial = 2; - - if (!rb_parent(parent)) - p = &key_serial_tree.rb_node; - else if (rb_parent(parent)->rb_left == parent) - p = &(rb_parent(parent)->rb_left); - else - p = &(rb_parent(parent)->rb_right); + if (key->serial < 3) { + key->serial = 3; + goto attempt_insertion; + } parent = rb_next(parent); if (!parent) - break; + goto attempt_insertion; xkey = rb_entry(parent, struct key, serial_node); if (key->serial < xkey->serial) - goto insert_here; + goto attempt_insertion; } - /* we've found a suitable hole - arrange for this key to occupy it */ -insert_here: - rb_link_node(&key->serial_node, parent, p); - rb_insert_color(&key->serial_node, &key_serial_tree); - - spin_unlock(&key_serial_lock); - } /* end key_alloc_serial() */ /*****************************************************************************/ diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 44e9cd47054..65fb5e8ea94 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1120,8 +1120,8 @@ static int file_has_perm(struct task_struct *tsk, { struct task_security_struct *tsec = tsk->security; struct file_security_struct *fsec = file->f_security; - struct vfsmount *mnt = file->f_vfsmnt; - struct dentry *dentry = file->f_dentry; + struct vfsmount *mnt = file->f_path.mnt; + struct dentry *dentry = file->f_path.dentry; struct inode *inode = dentry->d_inode; struct avc_audit_data ad; int rc; @@ -1581,7 +1581,7 @@ static int selinux_bprm_alloc_security(struct linux_binprm *bprm) static int selinux_bprm_set_security(struct linux_binprm *bprm) { struct task_security_struct *tsec; - struct inode *inode = bprm->file->f_dentry->d_inode; + struct inode *inode = bprm->file->f_path.dentry->d_inode; struct inode_security_struct *isec; struct bprm_security_struct *bsec; u32 newsid; @@ -1621,10 +1621,10 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm) } AVC_AUDIT_DATA_INIT(&ad, FS); - ad.u.fs.mnt = bprm->file->f_vfsmnt; - ad.u.fs.dentry = bprm->file->f_dentry; + ad.u.fs.mnt = bprm->file->f_path.mnt; + ad.u.fs.dentry = bprm->file->f_path.dentry; - if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) + if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) newsid = tsec->sid; if (tsec->sid == newsid) { @@ -1695,9 +1695,10 @@ static inline void flush_unauthorized_files(struct files_struct * files) struct tty_struct *tty; struct fdtable *fdt; long j = -1; + int drop_tty = 0; mutex_lock(&tty_mutex); - tty = current->signal->tty; + tty = get_current_tty(); if (tty) { file_list_lock(); file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list); @@ -1707,15 +1708,17 @@ static inline void flush_unauthorized_files(struct files_struct * files) than using file_has_perm, as this particular open file may belong to another process and we are only interested in the inode-based check here. */ - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; if (inode_has_perm(current, inode, FILE__READ | FILE__WRITE, NULL)) { - /* Reset controlling tty. */ - current->signal->tty = NULL; - current->signal->tty_old_pgrp = 0; + drop_tty = 1; } } file_list_unlock(); + + /* Reset controlling tty. */ + if (drop_tty) + proc_set_tty(current, NULL); } mutex_unlock(&tty_mutex); @@ -1731,7 +1734,7 @@ static inline void flush_unauthorized_files(struct files_struct * files) j++; i = j * __NFDBITS; fdt = files_fdtable(files); - if (i >= fdt->max_fds || i >= fdt->max_fdset) + if (i >= fdt->max_fds) break; set = fdt->open_fds->fds_bits[j]; if (!set) @@ -2417,7 +2420,7 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t static int selinux_file_permission(struct file *file, int mask) { int rc; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; if (!mask) { /* No permission to check. Existence test. */ @@ -2594,7 +2597,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd, switch (cmd) { case F_SETFL: - if (!file->f_dentry || !file->f_dentry->d_inode) { + if (!file->f_path.dentry || !file->f_path.dentry->d_inode) { err = -EINVAL; break; } @@ -2620,7 +2623,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd, case F_SETLK64: case F_SETLKW64: #endif - if (!file->f_dentry || !file->f_dentry->d_inode) { + if (!file->f_path.dentry || !file->f_path.dentry->d_inode) { err = -EINVAL; break; } diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h index 161eb571c82..31929e39f5c 100644 --- a/security/selinux/include/xfrm.h +++ b/security/selinux/include/xfrm.h @@ -37,6 +37,11 @@ int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, struct avc_audit_data *ad, u8 proto); int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); + +static inline void selinux_xfrm_notify_policyload(void) +{ + atomic_inc(&flow_cache_genid); +} #else static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, struct avc_audit_data *ad) @@ -55,6 +60,10 @@ static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int *sid = SECSID_NULL; return 0; } + +static inline void selinux_xfrm_notify_policyload(void) +{ +} #endif static inline void selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid) diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index cd244419c98..c8bf6e172f6 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -448,7 +448,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = { static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) { - ino_t ino = file->f_dentry->d_inode->i_ino; + ino_t ino = file->f_path.dentry->d_inode->i_ino; char *data; ssize_t rv; @@ -805,7 +805,7 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, goto out; } - inode = filep->f_dentry->d_inode; + inode = filep->f_path.dentry->d_inode; cur_enforcing = security_get_bool_value(inode->i_ino - BOOL_INO_OFFSET); if (cur_enforcing < 0) { ret = cur_enforcing; @@ -864,7 +864,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, if (new_value) new_value = 1; - inode = filep->f_dentry->d_inode; + inode = filep->f_path.dentry->d_inode; bool_pending_values[inode->i_ino - BOOL_INO_OFFSET] = new_value; length = count; @@ -965,7 +965,7 @@ static void sel_remove_bools(struct dentry *de) file_list_lock(); list_for_each(p, &sb->s_files) { struct file * filp = list_entry(p, struct file, f_u.fu_list); - struct dentry * dentry = filp->f_dentry; + struct dentry * dentry = filp->f_path.dentry; if (dentry->d_parent != de) { continue; diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h index 0562bacb7b9..2eee0dab524 100644 --- a/security/selinux/ss/context.h +++ b/security/selinux/ss/context.h @@ -55,6 +55,29 @@ out: return rc; } +/* + * Sets both levels in the MLS range of 'dst' to the low level of 'src'. + */ +static inline int mls_context_cpy_low(struct context *dst, struct context *src) +{ + int rc; + + if (!selinux_mls_enabled) + return 0; + + dst->range.level[0].sens = src->range.level[0].sens; + rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); + if (rc) + goto out; + + dst->range.level[1].sens = src->range.level[0].sens; + rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[0].cat); + if (rc) + ebitmap_destroy(&dst->range.level[0].cat); +out: + return rc; +} + static inline int mls_context_cmp(struct context *c1, struct context *c2) { if (!selinux_mls_enabled) diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index b4f682dc13f..4a8bab2f3c7 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -270,7 +270,7 @@ int mls_context_to_sid(char oldc, if (!defcon) goto out; - rc = mls_copy_context(context, defcon); + rc = mls_context_cpy(context, defcon); goto out; } @@ -401,26 +401,6 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask) } /* - * Copies the effective MLS range from `src' into `dst'. - */ -static inline int mls_scopy_context(struct context *dst, - struct context *src) -{ - int l, rc = 0; - - /* Copy the MLS range from the source context */ - for (l = 0; l < 2; l++) { - dst->range.level[l].sens = src->range.level[0].sens; - rc = ebitmap_cpy(&dst->range.level[l].cat, - &src->range.level[0].cat); - if (rc) - break; - } - - return rc; -} - -/* * Copies the MLS range `range' into `context'. */ static inline int mls_range_set(struct context *context, @@ -552,19 +532,19 @@ int mls_compute_sid(struct context *scontext, case AVTAB_CHANGE: if (tclass == SECCLASS_PROCESS) /* Use the process MLS attributes. */ - return mls_copy_context(newcontext, scontext); + return mls_context_cpy(newcontext, scontext); else /* Use the process effective MLS attributes. */ - return mls_scopy_context(newcontext, scontext); + return mls_context_cpy_low(newcontext, scontext); case AVTAB_MEMBER: /* Only polyinstantiate the MLS attributes if the type is being polyinstantiated */ if (newcontext->type != tcontext->type) { /* Use the process effective MLS attributes. */ - return mls_scopy_context(newcontext, scontext); + return mls_context_cpy_low(newcontext, scontext); } else { /* Use the related object MLS attributes. */ - return mls_copy_context(newcontext, tcontext); + return mls_context_cpy(newcontext, tcontext); } default: return -EINVAL; diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h index 661d6fc7696..096d1b4ef7f 100644 --- a/security/selinux/ss/mls.h +++ b/security/selinux/ss/mls.h @@ -24,26 +24,6 @@ #include "context.h" #include "policydb.h" -/* - * Copies the MLS range from `src' into `dst'. - */ -static inline int mls_copy_context(struct context *dst, - struct context *src) -{ - int l, rc = 0; - - /* Copy the MLS range from the source context */ - for (l = 0; l < 2; l++) { - dst->range.level[l].sens = src->range.level[l].sens; - rc = ebitmap_cpy(&dst->range.level[l].cat, - &src->range.level[l].cat); - if (rc) - break; - } - - return rc; -} - int mls_compute_context_len(struct context *context); void mls_sid_to_context(struct context *context, char **scontext); int mls_context_isvalid(struct policydb *p, struct context *c); diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index bdb7070dd3d..ca9154dc5d8 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -1299,6 +1299,7 @@ int security_load_policy(void *data, size_t len) avc_ss_reset(seqno); selnl_notify_policyload(seqno); selinux_netlbl_cache_invalidate(); + selinux_xfrm_notify_policyload(); return 0; } @@ -1354,6 +1355,7 @@ int security_load_policy(void *data, size_t len) avc_ss_reset(seqno); selnl_notify_policyload(seqno); selinux_netlbl_cache_invalidate(); + selinux_xfrm_notify_policyload(); return 0; @@ -1853,6 +1855,7 @@ out: if (!rc) { avc_ss_reset(seqno); selnl_notify_policyload(seqno); + selinux_xfrm_notify_policyload(); } return rc; } @@ -1916,11 +1919,10 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) newcon.user = context1->user; newcon.role = context1->role; newcon.type = context1->type; - rc = mls_copy_context(&newcon, context2); + rc = mls_context_cpy(&newcon, context2); if (rc) goto out_unlock; - /* Check the validity of the new context. */ if (!policydb_context_isvalid(&policydb, &newcon)) { rc = convert_context_handle_invalid_context(&newcon); @@ -2492,9 +2494,9 @@ static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid) rc = netlbl_socket_setattr(sock, &secattr); if (rc == 0) { - spin_lock(&sksec->nlbl_lock); + spin_lock_bh(&sksec->nlbl_lock); sksec->nlbl_state = NLBL_LABELED; - spin_unlock(&sksec->nlbl_lock); + spin_unlock_bh(&sksec->nlbl_lock); } netlbl_socket_setsid_return: @@ -2660,9 +2662,11 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask) rcu_read_unlock(); return 0; } - lock_sock(sock->sk); + local_bh_disable(); + bh_lock_sock_nested(sock->sk); rc = selinux_netlbl_socket_setsid(sock, sksec->sid); - release_sock(sock->sk); + bh_unlock_sock(sock->sk); + local_bh_enable(); rcu_read_unlock(); return rc; |