diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/commoncap.c | 2 | ||||
-rw-r--r-- | security/keys/proc.c | 34 | ||||
-rw-r--r-- | security/selinux/hooks.c | 70 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 2 |
4 files changed, 49 insertions, 59 deletions
diff --git a/security/commoncap.c b/security/commoncap.c index 48620c93d697..1ce701fcb3f3 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -449,6 +449,8 @@ int cap_inode_getsecurity(struct inode *inode, const char *name, void **buffer, magic |= VFS_CAP_FLAGS_EFFECTIVE; memcpy(&cap->data, &nscap->data, sizeof(__le32) * 2 * VFS_CAP_U32); cap->magic_etc = cpu_to_le32(magic); + } else { + size = -ENOMEM; } } kfree(tmpbuf); diff --git a/security/keys/proc.c b/security/keys/proc.c index fbc4af5c6c9f..5af2934965d8 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c @@ -18,7 +18,6 @@ #include <asm/errno.h> #include "internal.h" -static int proc_keys_open(struct inode *inode, struct file *file); static void *proc_keys_start(struct seq_file *p, loff_t *_pos); static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos); static void proc_keys_stop(struct seq_file *p, void *v); @@ -31,14 +30,6 @@ static const struct seq_operations proc_keys_ops = { .show = proc_keys_show, }; -static const struct file_operations proc_keys_fops = { - .open = proc_keys_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static int proc_key_users_open(struct inode *inode, struct file *file); static void *proc_key_users_start(struct seq_file *p, loff_t *_pos); static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos); static void proc_key_users_stop(struct seq_file *p, void *v); @@ -51,13 +42,6 @@ static const struct seq_operations proc_key_users_ops = { .show = proc_key_users_show, }; -static const struct file_operations proc_key_users_fops = { - .open = proc_key_users_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - /* * Declare the /proc files. */ @@ -65,11 +49,11 @@ static int __init key_proc_init(void) { struct proc_dir_entry *p; - p = proc_create("keys", 0, NULL, &proc_keys_fops); + p = proc_create_seq("keys", 0, NULL, &proc_keys_ops); if (!p) panic("Cannot create /proc/keys\n"); - p = proc_create("key-users", 0, NULL, &proc_key_users_fops); + p = proc_create_seq("key-users", 0, NULL, &proc_key_users_ops); if (!p) panic("Cannot create /proc/key-users\n"); @@ -96,11 +80,6 @@ static struct rb_node *key_serial_next(struct seq_file *p, struct rb_node *n) return n; } -static int proc_keys_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &proc_keys_ops); -} - static struct key *find_ge_key(struct seq_file *p, key_serial_t id) { struct user_namespace *user_ns = seq_user_ns(p); @@ -293,15 +272,6 @@ static struct rb_node *key_user_first(struct user_namespace *user_ns, struct rb_ return __key_user_next(user_ns, n); } -/* - * Implement "/proc/key-users" to provides a list of the key users and their - * quotas. - */ -static int proc_key_users_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &proc_key_users_ops); -} - static void *proc_key_users_start(struct seq_file *p, loff_t *_pos) __acquires(key_user_lock) { diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index b02315183b2f..99c4675952f7 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1567,8 +1567,15 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent /* Called from d_instantiate or d_splice_alias. */ dentry = dget(opt_dentry); } else { - /* Called from selinux_complete_init, try to find a dentry. */ + /* + * Called from selinux_complete_init, try to find a dentry. + * Some filesystems really want a connected one, so try + * that first. We could split SECURITY_FS_USE_XATTR in + * two, depending upon that... + */ dentry = d_find_alias(inode); + if (!dentry) + dentry = d_find_any_alias(inode); } if (!dentry) { /* @@ -1673,14 +1680,19 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) { /* We must have a dentry to determine the label on * procfs inodes */ - if (opt_dentry) + if (opt_dentry) { /* Called from d_instantiate or * d_splice_alias. */ dentry = dget(opt_dentry); - else + } else { /* Called from selinux_complete_init, try to - * find a dentry. */ + * find a dentry. Some filesystems really want + * a connected one, so try that first. + */ dentry = d_find_alias(inode); + if (!dentry) + dentry = d_find_any_alias(inode); + } /* * This can be hit on boot when a file is accessed * before the policy is loaded. When we load policy we @@ -4575,6 +4587,7 @@ static int selinux_socket_post_create(struct socket *sock, int family, static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) { struct sock *sk = sock->sk; + struct sk_security_struct *sksec = sk->sk_security; u16 family; int err; @@ -4586,11 +4599,11 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in family = sk->sk_family; if (family == PF_INET || family == PF_INET6) { char *addrp; - struct sk_security_struct *sksec = sk->sk_security; struct common_audit_data ad; struct lsm_network_audit net = {0,}; struct sockaddr_in *addr4 = NULL; struct sockaddr_in6 *addr6 = NULL; + u16 family_sa = address->sa_family; unsigned short snum; u32 sid, node_perm; @@ -4600,11 +4613,20 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in * need to check address->sa_family as it is possible to have * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET. */ - switch (address->sa_family) { + switch (family_sa) { + case AF_UNSPEC: case AF_INET: if (addrlen < sizeof(struct sockaddr_in)) return -EINVAL; addr4 = (struct sockaddr_in *)address; + if (family_sa == AF_UNSPEC) { + /* see __inet_bind(), we only want to allow + * AF_UNSPEC if the address is INADDR_ANY + */ + if (addr4->sin_addr.s_addr != htonl(INADDR_ANY)) + goto err_af; + family_sa = AF_INET; + } snum = ntohs(addr4->sin_port); addrp = (char *)&addr4->sin_addr.s_addr; break; @@ -4616,15 +4638,14 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in addrp = (char *)&addr6->sin6_addr.s6_addr; break; default: - /* Note that SCTP services expect -EINVAL, whereas - * others expect -EAFNOSUPPORT. - */ - if (sksec->sclass == SECCLASS_SCTP_SOCKET) - return -EINVAL; - else - return -EAFNOSUPPORT; + goto err_af; } + ad.type = LSM_AUDIT_DATA_NET; + ad.u.net = &net; + ad.u.net->sport = htons(snum); + ad.u.net->family = family_sa; + if (snum) { int low, high; @@ -4636,10 +4657,6 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in snum, &sid); if (err) goto out; - ad.type = LSM_AUDIT_DATA_NET; - ad.u.net = &net; - ad.u.net->sport = htons(snum); - ad.u.net->family = family; err = avc_has_perm(&selinux_state, sksec->sid, sid, sksec->sclass, @@ -4671,16 +4688,11 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in break; } - err = sel_netnode_sid(addrp, family, &sid); + err = sel_netnode_sid(addrp, family_sa, &sid); if (err) goto out; - ad.type = LSM_AUDIT_DATA_NET; - ad.u.net = &net; - ad.u.net->sport = htons(snum); - ad.u.net->family = family; - - if (address->sa_family == AF_INET) + if (family_sa == AF_INET) ad.u.net->v4info.saddr = addr4->sin_addr.s_addr; else ad.u.net->v6info.saddr = addr6->sin6_addr; @@ -4693,6 +4705,11 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in } out: return err; +err_af: + /* Note that SCTP services expect -EINVAL, others -EAFNOSUPPORT. */ + if (sksec->sclass == SECCLASS_SCTP_SOCKET) + return -EINVAL; + return -EAFNOSUPPORT; } /* This supports connect(2) and SCTP connect services such as sctp_connectx(3) @@ -4770,7 +4787,7 @@ static int selinux_socket_connect_helper(struct socket *sock, ad.type = LSM_AUDIT_DATA_NET; ad.u.net = &net; ad.u.net->dport = htons(snum); - ad.u.net->family = sk->sk_family; + ad.u.net->family = address->sa_family; err = avc_has_perm(&selinux_state, sksec->sid, sid, sksec->sclass, perm, &ad); if (err) @@ -5271,6 +5288,7 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname, while (walk_size < addrlen) { addr = addr_buf; switch (addr->sa_family) { + case AF_UNSPEC: case AF_INET: len = sizeof(struct sockaddr_in); break; @@ -5278,7 +5296,7 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname, len = sizeof(struct sockaddr_in6); break; default: - return -EAFNOSUPPORT; + return -EINVAL; } err = -EINVAL; diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 8057e19dc15f..3ce225e3f142 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -1494,7 +1494,7 @@ static int security_context_to_sid_core(struct selinux_state *state, scontext_len, &context, def_sid); if (rc == -EINVAL && force) { context.str = str; - context.len = scontext_len; + context.len = strlen(str) + 1; str = NULL; } else if (rc) goto out_unlock; |