aboutsummaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/keys/key.c33
-rw-r--r--security/selinux/hooks.c33
-rw-r--r--security/selinux/include/xfrm.h9
-rw-r--r--security/selinux/selinuxfs.c8
-rw-r--r--security/selinux/ss/context.h23
-rw-r--r--security/selinux/ss/mls.c30
-rw-r--r--security/selinux/ss/mls.h20
-rw-r--r--security/selinux/ss/services.c16
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;