summaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/integrity/ima/Kconfig3
-rw-r--r--security/integrity/ima/Makefile3
-rw-r--r--security/integrity/ima/ima.h9
-rw-r--r--security/integrity/ima/ima_api.c4
-rw-r--r--security/integrity/ima/ima_audit.c3
-rw-r--r--security/integrity/ima/ima_fs.c11
-rw-r--r--security/integrity/ima/ima_init.c5
-rw-r--r--security/integrity/ima/ima_main.c50
-rw-r--r--security/integrity/ima/ima_policy.c2
-rw-r--r--security/keys/compat.c4
-rw-r--r--security/keys/internal.h4
-rw-r--r--security/keys/keyctl.c28
-rw-r--r--security/keys/keyring.c2
-rw-r--r--security/keys/process_keys.c5
-rw-r--r--security/selinux/avc.c2
-rw-r--r--security/selinux/hooks.c31
-rw-r--r--security/selinux/include/security.h2
-rw-r--r--security/selinux/netlink.c17
-rw-r--r--security/selinux/selinuxfs.c6
-rw-r--r--security/smack/smack.h14
-rw-r--r--security/smack/smack_access.c9
-rw-r--r--security/smack/smack_lsm.c25
-rw-r--r--security/smack/smackfs.c61
23 files changed, 166 insertions, 134 deletions
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 35664fe6daa1..b9c1219924f1 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -38,8 +38,9 @@ config IMA_MEASURE_PCR_IDX
measurement list. If unsure, use the default 10.
config IMA_AUDIT
- bool
+ bool "Enables auditing support"
depends on IMA
+ depends on AUDIT
default y
help
This option adds a kernel parameter 'ima_audit', which
diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile
index 5690c021de8f..5f740f6971e1 100644
--- a/security/integrity/ima/Makefile
+++ b/security/integrity/ima/Makefile
@@ -6,4 +6,5 @@
obj-$(CONFIG_IMA) += ima.o
ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \
- ima_policy.o ima_audit.o
+ ima_policy.o
+ima-$(CONFIG_IMA_AUDIT) += ima_audit.o
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 3ccf7acac6df..e7c99fd0d223 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -61,10 +61,19 @@ struct ima_queue_entry {
};
extern struct list_head ima_measurements; /* list of all measurements */
+#ifdef CONFIG_IMA_AUDIT
/* declarations */
void integrity_audit_msg(int audit_msgno, struct inode *inode,
const unsigned char *fname, const char *op,
const char *cause, int result, int info);
+#else
+static inline void integrity_audit_msg(int audit_msgno, struct inode *inode,
+ const unsigned char *fname,
+ const char *op, const char *cause,
+ int result, int info)
+{
+}
+#endif
/* Internal IMA function definitions */
int ima_init(void);
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 88a2788b981d..032ff03ad907 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -175,7 +175,9 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
}
memset(&entry->template, 0, sizeof(entry->template));
memcpy(entry->template.digest, iint->digest, IMA_DIGEST_SIZE);
- strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX);
+ strcpy(entry->template.file_name,
+ (strlen(filename) > IMA_EVENT_NAME_LEN_MAX) ?
+ file->f_dentry->d_name.name : filename);
result = ima_store_template(entry, violation, inode);
if (!result || result == -EEXIST)
diff --git a/security/integrity/ima/ima_audit.c b/security/integrity/ima/ima_audit.c
index 21e96bf188df..7a57f6769e9c 100644
--- a/security/integrity/ima/ima_audit.c
+++ b/security/integrity/ima/ima_audit.c
@@ -17,8 +17,6 @@
static int ima_audit;
-#ifdef CONFIG_IMA_AUDIT
-
/* ima_audit_setup - enable informational auditing messages */
static int __init ima_audit_setup(char *str)
{
@@ -29,7 +27,6 @@ static int __init ima_audit_setup(char *str)
return 1;
}
__setup("ima_audit=", ima_audit_setup);
-#endif
void integrity_audit_msg(int audit_msgno, struct inode *inode,
const unsigned char *fname, const char *op,
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index e1aa2b482dd2..38477c9c3415 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -367,20 +367,11 @@ int __init ima_fs_init(void)
return 0;
out:
- securityfs_remove(runtime_measurements_count);
- securityfs_remove(ascii_runtime_measurements);
- securityfs_remove(binary_runtime_measurements);
- securityfs_remove(ima_dir);
- securityfs_remove(ima_policy);
- return -1;
-}
-
-void __exit ima_fs_cleanup(void)
-{
securityfs_remove(violations);
securityfs_remove(runtime_measurements_count);
securityfs_remove(ascii_runtime_measurements);
securityfs_remove(binary_runtime_measurements);
securityfs_remove(ima_dir);
securityfs_remove(ima_policy);
+ return -1;
}
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
index 17f1f060306f..b5dfd534f13d 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -90,8 +90,3 @@ int __init ima_init(void)
return ima_fs_init();
}
-
-void __exit ima_cleanup(void)
-{
- ima_fs_cleanup();
-}
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index b17be79b9cf2..be8294915cf7 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -54,6 +54,7 @@ static void ima_rdwr_violation_check(struct file *file)
fmode_t mode = file->f_mode;
int rc;
bool send_tomtou = false, send_writers = false;
+ unsigned char *pathname = NULL, *pathbuf = NULL;
if (!S_ISREG(inode->i_mode) || !ima_initialized)
return;
@@ -75,12 +76,27 @@ static void ima_rdwr_violation_check(struct file *file)
out:
mutex_unlock(&inode->i_mutex);
+ if (!send_tomtou && !send_writers)
+ return;
+
+ /* We will allow 11 spaces for ' (deleted)' to be appended */
+ pathbuf = kmalloc(PATH_MAX + 11, GFP_KERNEL);
+ if (pathbuf) {
+ pathname = d_path(&file->f_path, pathbuf, PATH_MAX + 11);
+ if (IS_ERR(pathname))
+ pathname = NULL;
+ else if (strlen(pathname) > IMA_EVENT_NAME_LEN_MAX)
+ pathname = NULL;
+ }
if (send_tomtou)
- ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
- "ToMToU");
+ ima_add_violation(inode,
+ !pathname ? dentry->d_name.name : pathname,
+ "invalid_pcr", "ToMToU");
if (send_writers)
- ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
- "open_writers");
+ ima_add_violation(inode,
+ !pathname ? dentry->d_name.name : pathname,
+ "invalid_pcr", "open_writers");
+ kfree(pathbuf);
}
static void ima_check_last_writer(struct integrity_iint_cache *iint,
@@ -123,6 +139,7 @@ static int process_measurement(struct file *file, const unsigned char *filename,
{
struct inode *inode = file->f_dentry->d_inode;
struct integrity_iint_cache *iint;
+ unsigned char *pathname = NULL, *pathbuf = NULL;
int rc = 0;
if (!ima_initialized || !S_ISREG(inode->i_mode))
@@ -147,8 +164,21 @@ retry:
goto out;
rc = ima_collect_measurement(iint, file);
- if (!rc)
- ima_store_measurement(iint, file, filename);
+ if (rc != 0)
+ goto out;
+
+ if (function != BPRM_CHECK) {
+ /* We will allow 11 spaces for ' (deleted)' to be appended */
+ pathbuf = kmalloc(PATH_MAX + 11, GFP_KERNEL);
+ if (pathbuf) {
+ pathname =
+ d_path(&file->f_path, pathbuf, PATH_MAX + 11);
+ if (IS_ERR(pathname))
+ pathname = NULL;
+ }
+ }
+ ima_store_measurement(iint, file, !pathname ? filename : pathname);
+ kfree(pathbuf);
out:
mutex_unlock(&iint->mutex);
return rc;
@@ -228,15 +258,11 @@ static int __init init_ima(void)
int error;
error = ima_init();
- ima_initialized = 1;
+ if (!error)
+ ima_initialized = 1;
return error;
}
-static void __exit cleanup_ima(void)
-{
- ima_cleanup();
-}
-
late_initcall(init_ima); /* Start IMA after the TPM is available */
MODULE_DESCRIPTION("Integrity Measurement Architecture");
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index d8edff209bf3..1a9583008aae 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -63,6 +63,8 @@ static struct ima_measure_rule_entry default_rules[] = {
{.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC},
{.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC},
{.action = DONT_MEASURE,.fsmagic = RAMFS_MAGIC,.flags = IMA_FSMAGIC},
+ {.action = DONT_MEASURE,.fsmagic = DEVPTS_SUPER_MAGIC,.flags = IMA_FSMAGIC},
+ {.action = DONT_MEASURE,.fsmagic = BINFMTFS_MAGIC,.flags = IMA_FSMAGIC},
{.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC},
{.action = DONT_MEASURE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC},
{.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC,
diff --git a/security/keys/compat.c b/security/keys/compat.c
index c92d42b021aa..1c261763f479 100644
--- a/security/keys/compat.c
+++ b/security/keys/compat.c
@@ -24,7 +24,7 @@
*
* If successful, 0 will be returned.
*/
-long compat_keyctl_instantiate_key_iov(
+static long compat_keyctl_instantiate_key_iov(
key_serial_t id,
const struct compat_iovec __user *_payload_iov,
unsigned ioc,
@@ -33,7 +33,7 @@ long compat_keyctl_instantiate_key_iov(
struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
long ret;
- if (_payload_iov == 0 || ioc == 0)
+ if (!_payload_iov || !ioc)
goto no_payload;
ret = compat_rw_copy_check_uvector(WRITE, _payload_iov, ioc,
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 3dcbf86b0d31..22ff05269e3d 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -149,7 +149,7 @@ extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags,
#define KEY_LOOKUP_FOR_UNLINK 0x04
extern long join_session_keyring(const char *name);
-extern void key_change_session_keyring(struct task_work *twork);
+extern void key_change_session_keyring(struct callback_head *twork);
extern struct work_struct key_gc_work;
extern unsigned key_gc_delay;
@@ -242,7 +242,7 @@ extern long keyctl_instantiate_key_iov(key_serial_t,
extern long keyctl_invalidate_key(key_serial_t);
extern long keyctl_instantiate_key_common(key_serial_t,
- const struct iovec __user *,
+ const struct iovec *,
unsigned, size_t, key_serial_t);
/*
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 0f5b3f027299..3364fbf46807 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -1106,7 +1106,7 @@ long keyctl_instantiate_key_iov(key_serial_t id,
struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
long ret;
- if (_payload_iov == 0 || ioc == 0)
+ if (!_payload_iov || !ioc)
goto no_payload;
ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc,
@@ -1456,7 +1456,7 @@ long keyctl_session_to_parent(void)
{
struct task_struct *me, *parent;
const struct cred *mycred, *pcred;
- struct task_work *newwork, *oldwork;
+ struct callback_head *newwork, *oldwork;
key_ref_t keyring_r;
struct cred *cred;
int ret;
@@ -1466,19 +1466,17 @@ long keyctl_session_to_parent(void)
return PTR_ERR(keyring_r);
ret = -ENOMEM;
- newwork = kmalloc(sizeof(struct task_work), GFP_KERNEL);
- if (!newwork)
- goto error_keyring;
/* our parent is going to need a new cred struct, a new tgcred struct
* and new security data, so we allocate them here to prevent ENOMEM in
* our parent */
cred = cred_alloc_blank();
if (!cred)
- goto error_newwork;
+ goto error_keyring;
+ newwork = &cred->rcu;
cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r);
- init_task_work(newwork, key_change_session_keyring, cred);
+ init_task_work(newwork, key_change_session_keyring);
me = current;
rcu_read_lock();
@@ -1488,6 +1486,7 @@ long keyctl_session_to_parent(void)
oldwork = NULL;
parent = me->real_parent;
+ task_lock(parent);
/* the parent mustn't be init and mustn't be a kernel thread */
if (parent->pid <= 1 || !parent->mm)
goto unlock;
@@ -1531,20 +1530,15 @@ long keyctl_session_to_parent(void)
if (!ret)
newwork = NULL;
unlock:
+ task_unlock(parent);
write_unlock_irq(&tasklist_lock);
rcu_read_unlock();
- if (oldwork) {
- put_cred(oldwork->data);
- kfree(oldwork);
- }
- if (newwork) {
- put_cred(newwork->data);
- kfree(newwork);
- }
+ if (oldwork)
+ put_cred(container_of(oldwork, struct cred, rcu));
+ if (newwork)
+ put_cred(cred);
return ret;
-error_newwork:
- kfree(newwork);
error_keyring:
key_ref_put(keyring_r);
return ret;
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 7445875f6818..81e7852d281d 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -751,6 +751,7 @@ static void keyring_unlink_rcu_disposal(struct rcu_head *rcu)
int __key_link_begin(struct key *keyring, const struct key_type *type,
const char *description, unsigned long *_prealloc)
__acquires(&keyring->sem)
+ __acquires(&keyring_serialise_link_sem)
{
struct keyring_list *klist, *nklist;
unsigned long prealloc;
@@ -960,6 +961,7 @@ void __key_link(struct key *keyring, struct key *key,
void __key_link_end(struct key *keyring, struct key_type *type,
unsigned long prealloc)
__releases(&keyring->sem)
+ __releases(&keyring_serialise_link_sem)
{
BUG_ON(type == NULL);
BUG_ON(type->name == NULL);
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 4ad54eea1ea4..54339cfd6734 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -834,12 +834,11 @@ error:
* Replace a process's session keyring on behalf of one of its children when
* the target process is about to resume userspace execution.
*/
-void key_change_session_keyring(struct task_work *twork)
+void key_change_session_keyring(struct callback_head *twork)
{
const struct cred *old = current_cred();
- struct cred *new = twork->data;
+ struct cred *new = container_of(twork, struct cred, rcu);
- kfree(twork);
if (unlikely(current->flags & PF_EXITING)) {
put_cred(new);
return;
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 68d82daed257..4d3fab47e643 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -274,7 +274,7 @@ static struct avc_node *avc_alloc_node(void)
{
struct avc_node *node;
- node = kmem_cache_zalloc(avc_node_cachep, GFP_ATOMIC);
+ node = kmem_cache_zalloc(avc_node_cachep, GFP_ATOMIC|__GFP_NOMEMALLOC);
if (!node)
goto out;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index ffd8900a38e8..6c77f63c7591 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2129,7 +2129,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,
int fd;
j++;
- i = j * __NFDBITS;
+ i = j * BITS_PER_LONG;
fdt = files_fdtable(files);
if (i >= fdt->max_fds)
break;
@@ -2157,8 +2157,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,
get_file(devnull);
} else {
devnull = dentry_open(
- dget(selinux_null),
- mntget(selinuxfs_mount),
+ &selinux_null,
O_RDWR, cred);
if (IS_ERR(devnull)) {
devnull = NULL;
@@ -2792,11 +2791,16 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
/* We strip a nul only if it is at the end, otherwise the
* context contains a nul and we should audit that */
- str = value;
- if (str[size - 1] == '\0')
- audit_size = size - 1;
- else
- audit_size = size;
+ if (value) {
+ str = value;
+ if (str[size - 1] == '\0')
+ audit_size = size - 1;
+ else
+ audit_size = size;
+ } else {
+ str = "";
+ audit_size = 0;
+ }
ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
audit_log_format(ab, "op=setxattr invalid_context=");
audit_log_n_untrustedstring(ab, value, audit_size);
@@ -3181,6 +3185,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
case F_GETFL:
case F_GETOWN:
case F_GETSIG:
+ case F_GETOWNER_UIDS:
/* Just check FD__USE permission */
err = file_has_perm(cred, file, 0);
break;
@@ -5763,21 +5768,21 @@ static struct nf_hook_ops selinux_ipv4_ops[] = {
{
.hook = selinux_ipv4_postroute,
.owner = THIS_MODULE,
- .pf = PF_INET,
+ .pf = NFPROTO_IPV4,
.hooknum = NF_INET_POST_ROUTING,
.priority = NF_IP_PRI_SELINUX_LAST,
},
{
.hook = selinux_ipv4_forward,
.owner = THIS_MODULE,
- .pf = PF_INET,
+ .pf = NFPROTO_IPV4,
.hooknum = NF_INET_FORWARD,
.priority = NF_IP_PRI_SELINUX_FIRST,
},
{
.hook = selinux_ipv4_output,
.owner = THIS_MODULE,
- .pf = PF_INET,
+ .pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_OUT,
.priority = NF_IP_PRI_SELINUX_FIRST,
}
@@ -5789,14 +5794,14 @@ static struct nf_hook_ops selinux_ipv6_ops[] = {
{
.hook = selinux_ipv6_postroute,
.owner = THIS_MODULE,
- .pf = PF_INET6,
+ .pf = NFPROTO_IPV6,
.hooknum = NF_INET_POST_ROUTING,
.priority = NF_IP6_PRI_SELINUX_LAST,
},
{
.hook = selinux_ipv6_forward,
.owner = THIS_MODULE,
- .pf = PF_INET6,
+ .pf = NFPROTO_IPV6,
.hooknum = NF_INET_FORWARD,
.priority = NF_IP6_PRI_SELINUX_FIRST,
}
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index dde2005407aa..6d3885165d14 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -221,7 +221,7 @@ extern void selinux_status_update_policyload(int seqno);
extern void selinux_complete_init(void);
extern int selinux_disable(void);
extern void exit_sel_fs(void);
-extern struct dentry *selinux_null;
+extern struct path selinux_null;
extern struct vfsmount *selinuxfs_mount;
extern void selnl_notify_setenforce(int val);
extern void selnl_notify_policyload(u32 seqno);
diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c
index 161e01a6c7ef..8a77725423e0 100644
--- a/security/selinux/netlink.c
+++ b/security/selinux/netlink.c
@@ -19,6 +19,7 @@
#include <linux/netlink.h>
#include <linux/selinux_netlink.h>
#include <net/net_namespace.h>
+#include <net/netlink.h>
#include "security.h"
@@ -47,7 +48,7 @@ static void selnl_add_payload(struct nlmsghdr *nlh, int len, int msgtype, void *
{
switch (msgtype) {
case SELNL_MSG_SETENFORCE: {
- struct selnl_msg_setenforce *msg = NLMSG_DATA(nlh);
+ struct selnl_msg_setenforce *msg = nlmsg_data(nlh);
memset(msg, 0, len);
msg->val = *((int *)data);
@@ -55,7 +56,7 @@ static void selnl_add_payload(struct nlmsghdr *nlh, int len, int msgtype, void *
}
case SELNL_MSG_POLICYLOAD: {
- struct selnl_msg_policyload *msg = NLMSG_DATA(nlh);
+ struct selnl_msg_policyload *msg = nlmsg_data(nlh);
memset(msg, 0, len);
msg->seqno = *((u32 *)data);
@@ -81,7 +82,9 @@ static void selnl_notify(int msgtype, void *data)
goto oom;
tmp = skb->tail;
- nlh = NLMSG_PUT(skb, 0, 0, msgtype, len);
+ nlh = nlmsg_put(skb, 0, 0, msgtype, len, 0);
+ if (!nlh)
+ goto out_kfree_skb;
selnl_add_payload(nlh, len, msgtype, data);
nlh->nlmsg_len = skb->tail - tmp;
NETLINK_CB(skb).dst_group = SELNLGRP_AVC;
@@ -89,7 +92,7 @@ static void selnl_notify(int msgtype, void *data)
out:
return;
-nlmsg_failure:
+out_kfree_skb:
kfree_skb(skb);
oom:
printk(KERN_ERR "SELinux: OOM in %s\n", __func__);
@@ -108,8 +111,12 @@ void selnl_notify_policyload(u32 seqno)
static int __init selnl_init(void)
{
+ struct netlink_kernel_cfg cfg = {
+ .groups = SELNLGRP_MAX,
+ };
+
selnl = netlink_kernel_create(&init_net, NETLINK_SELINUX,
- SELNLGRP_MAX, NULL, NULL, THIS_MODULE);
+ THIS_MODULE, &cfg);
if (selnl == NULL)
panic("SELinux: Cannot create netlink socket.");
netlink_set_nonroot(NETLINK_SELINUX, NL_NONROOT_RECV);
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 3ad290251288..298e695d6822 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -1297,7 +1297,7 @@ out:
#define NULL_FILE_NAME "null"
-struct dentry *selinux_null;
+struct path selinux_null;
static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf,
size_t count, loff_t *ppos)
@@ -1838,7 +1838,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent)
init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3));
d_add(dentry, inode);
- selinux_null = dentry;
+ selinux_null.dentry = dentry;
dentry = sel_make_dir(sb->s_root, "avc", &sel_last_ino);
if (IS_ERR(dentry)) {
@@ -1912,7 +1912,7 @@ static int __init init_sel_fs(void)
return err;
}
- selinuxfs_mount = kern_mount(&sel_fs_type);
+ selinux_null.mnt = selinuxfs_mount = kern_mount(&sel_fs_type);
if (IS_ERR(selinuxfs_mount)) {
printk(KERN_ERR "selinuxfs: could not mount!\n");
err = PTR_ERR(selinuxfs_mount);
diff --git a/security/smack/smack.h b/security/smack/smack.h
index cc361b8f3d13..99b36124f712 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -43,7 +43,6 @@ struct superblock_smack {
char *smk_hat;
char *smk_default;
int smk_initialized;
- spinlock_t smk_sblock; /* for initialization */
};
struct socket_smack {
@@ -284,6 +283,19 @@ static inline char *smk_of_current(void)
}
/*
+ * Is the task privileged and allowed to be privileged
+ * by the onlycap rule.
+ */
+static inline int smack_privileged(int cap)
+{
+ if (!capable(cap))
+ return 0;
+ if (smack_onlycap == NULL || smack_onlycap == smk_of_current())
+ return 1;
+ return 0;
+}
+
+/*
* logging functions
*/
#define SMACK_AUDIT_DENIED 0x1
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 9f3705e92712..db14689a21e0 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -220,14 +220,9 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
}
/*
- * Return if a specific label has been designated as the
- * only one that gets privilege and current does not
- * have that label.
+ * Allow for priviliged to override policy.
*/
- if (smack_onlycap != NULL && smack_onlycap != sp)
- goto out_audit;
-
- if (capable(CAP_MAC_OVERRIDE))
+ if (rc != 0 && smack_privileged(CAP_MAC_OVERRIDE))
rc = 0;
out_audit:
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index ee0bb5735f35..8221514cc997 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -217,7 +217,7 @@ static int smack_syslog(int typefrom_file)
int rc = 0;
char *sp = smk_of_current();
- if (capable(CAP_MAC_OVERRIDE))
+ if (smack_privileged(CAP_MAC_OVERRIDE))
return 0;
if (sp != smack_known_floor.smk_known)
@@ -251,7 +251,6 @@ static int smack_sb_alloc_security(struct super_block *sb)
sbsp->smk_floor = smack_known_floor.smk_known;
sbsp->smk_hat = smack_known_hat.smk_known;
sbsp->smk_initialized = 0;
- spin_lock_init(&sbsp->smk_sblock);
sb->s_security = sbsp;
@@ -332,13 +331,10 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
char *commap;
char *nsp;
- spin_lock(&sp->smk_sblock);
- if (sp->smk_initialized != 0) {
- spin_unlock(&sp->smk_sblock);
+ if (sp->smk_initialized != 0)
return 0;
- }
+
sp->smk_initialized = 1;
- spin_unlock(&sp->smk_sblock);
for (op = data; op != NULL; op = commap) {
commap = strchr(op, ',');
@@ -825,7 +821,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 ||
strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
- if (!capable(CAP_MAC_ADMIN))
+ if (!smack_privileged(CAP_MAC_ADMIN))
rc = -EPERM;
/*
* check label validity here so import wont fail on
@@ -835,7 +831,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
smk_import(value, size) == NULL)
rc = -EINVAL;
} else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
- if (!capable(CAP_MAC_ADMIN))
+ if (!smack_privileged(CAP_MAC_ADMIN))
rc = -EPERM;
if (size != TRANS_TRUE_SIZE ||
strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0)
@@ -931,7 +927,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0 ||
strcmp(name, XATTR_NAME_SMACKMMAP)) {
- if (!capable(CAP_MAC_ADMIN))
+ if (!smack_privileged(CAP_MAC_ADMIN))
rc = -EPERM;
} else
rc = cap_inode_removexattr(dentry, name);
@@ -1720,7 +1716,8 @@ static int smack_task_wait(struct task_struct *p)
* state into account in the decision as well as
* the smack value.
*/
- if (capable(CAP_MAC_OVERRIDE) || has_capability(p, CAP_MAC_OVERRIDE))
+ if (smack_privileged(CAP_MAC_OVERRIDE) ||
+ has_capability(p, CAP_MAC_OVERRIDE))
rc = 0;
/* we log only if we didn't get overriden */
out_log:
@@ -2721,7 +2718,7 @@ static int smack_setprocattr(struct task_struct *p, char *name,
if (p != current)
return -EPERM;
- if (!capable(CAP_MAC_ADMIN))
+ if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
if (value == NULL || size == 0 || size >= SMK_LONGLABEL)
@@ -2784,7 +2781,7 @@ static int smack_unix_stream_connect(struct sock *sock,
smk_ad_setfield_u_net_sk(&ad, other);
#endif
- if (!capable(CAP_MAC_OVERRIDE))
+ if (!smack_privileged(CAP_MAC_OVERRIDE))
rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad);
/*
@@ -2820,7 +2817,7 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other)
smk_ad_setfield_u_net_sk(&ad, other->sk);
#endif
- if (!capable(CAP_MAC_OVERRIDE))
+ if (!smack_privileged(CAP_MAC_OVERRIDE))
rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad);
return rc;
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 1810c9a4ed48..b1b768e4049a 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -215,28 +215,27 @@ static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list,
* @access: access string
* @rule: Smack rule
* @import: if non-zero, import labels
+ * @len: label length limit
*
* Returns 0 on success, -1 on failure
*/
static int smk_fill_rule(const char *subject, const char *object,
const char *access, struct smack_rule *rule,
- int import)
+ int import, int len)
{
- int rc = -1;
- int done;
const char *cp;
struct smack_known *skp;
if (import) {
- rule->smk_subject = smk_import(subject, 0);
+ rule->smk_subject = smk_import(subject, len);
if (rule->smk_subject == NULL)
return -1;
- rule->smk_object = smk_import(object, 0);
+ rule->smk_object = smk_import(object, len);
if (rule->smk_object == NULL)
return -1;
} else {
- cp = smk_parse_smack(subject, 0);
+ cp = smk_parse_smack(subject, len);
if (cp == NULL)
return -1;
skp = smk_find_entry(cp);
@@ -245,7 +244,7 @@ static int smk_fill_rule(const char *subject, const char *object,
return -1;
rule->smk_subject = skp->smk_known;
- cp = smk_parse_smack(object, 0);
+ cp = smk_parse_smack(object, len);
if (cp == NULL)
return -1;
skp = smk_find_entry(cp);
@@ -257,7 +256,7 @@ static int smk_fill_rule(const char *subject, const char *object,
rule->smk_access = 0;
- for (cp = access, done = 0; *cp && !done; cp++) {
+ for (cp = access; *cp != '\0'; cp++) {
switch (*cp) {
case '-':
break;
@@ -282,13 +281,11 @@ static int smk_fill_rule(const char *subject, const char *object,
rule->smk_access |= MAY_TRANSMUTE;
break;
default:
- done = 1;
- break;
+ return 0;
}
}
- rc = 0;
- return rc;
+ return 0;
}
/**
@@ -304,7 +301,8 @@ static int smk_parse_rule(const char *data, struct smack_rule *rule, int import)
int rc;
rc = smk_fill_rule(data, data + SMK_LABELLEN,
- data + SMK_LABELLEN + SMK_LABELLEN, rule, import);
+ data + SMK_LABELLEN + SMK_LABELLEN, rule, import,
+ SMK_LABELLEN);
return rc;
}
@@ -325,11 +323,11 @@ static int smk_parse_long_rule(const char *data, struct smack_rule *rule,
int datalen;
int rc = -1;
- /*
- * This is probably inefficient, but safe.
- */
+ /* This is inefficient */
datalen = strlen(data);
- subject = kzalloc(datalen, GFP_KERNEL);
+
+ /* Our first element can be 64 + \0 with no spaces */
+ subject = kzalloc(datalen + 1, GFP_KERNEL);
if (subject == NULL)
return -1;
object = kzalloc(datalen, GFP_KERNEL);
@@ -340,7 +338,7 @@ static int smk_parse_long_rule(const char *data, struct smack_rule *rule,
goto free_out_o;
if (sscanf(data, "%s %s %s", subject, object, access) == 3)
- rc = smk_fill_rule(subject, object, access, rule, import);
+ rc = smk_fill_rule(subject, object, access, rule, import, 0);
kfree(access);
free_out_o:
@@ -520,6 +518,9 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max)
if (strlen(srp->smk_subject) >= max || strlen(srp->smk_object) >= max)
return;
+ if (srp->smk_access == 0)
+ return;
+
seq_printf(s, "%s %s", srp->smk_subject, srp->smk_object);
seq_putc(s, ' ');
@@ -534,8 +535,6 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max)
seq_putc(s, 'a');
if (srp->smk_access & MAY_TRANSMUTE)
seq_putc(s, 't');
- if (srp->smk_access == 0)
- seq_putc(s, '-');
seq_putc(s, '\n');
}
@@ -595,13 +594,12 @@ static int smk_open_load(struct inode *inode, struct file *file)
static ssize_t smk_write_load(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
-
/*
* Must have privilege.
* No partial writes.
* Enough data must be present.
*/
- if (!capable(CAP_MAC_ADMIN))
+ if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
@@ -787,7 +785,7 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
* No partial writes.
* Enough data must be present.
*/
- if (!capable(CAP_MAC_ADMIN))
+ if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
if (*ppos != 0)
return -EINVAL;
@@ -1090,7 +1088,7 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
* "<addr/mask, as a.b.c.d/e><space><label>"
* "<addr, as a.b.c.d><space><label>"
*/
- if (!capable(CAP_MAC_ADMIN))
+ if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
if (*ppos != 0)
return -EINVAL;
@@ -1267,7 +1265,7 @@ static ssize_t smk_write_doi(struct file *file, const char __user *buf,
char temp[80];
int i;
- if (!capable(CAP_MAC_ADMIN))
+ if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
if (count >= sizeof(temp) || count == 0)
@@ -1334,7 +1332,7 @@ static ssize_t smk_write_direct(struct file *file, const char __user *buf,
char temp[80];
int i;
- if (!capable(CAP_MAC_ADMIN))
+ if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
if (count >= sizeof(temp) || count == 0)
@@ -1412,7 +1410,7 @@ static ssize_t smk_write_mapped(struct file *file, const char __user *buf,
char temp[80];
int i;
- if (!capable(CAP_MAC_ADMIN))
+ if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
if (count >= sizeof(temp) || count == 0)
@@ -1503,7 +1501,7 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
char *data;
int rc = count;
- if (!capable(CAP_MAC_ADMIN))
+ if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
data = kzalloc(count + 1, GFP_KERNEL);
@@ -1586,7 +1584,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
char *sp = smk_of_task(current->cred->security);
int rc = count;
- if (!capable(CAP_MAC_ADMIN))
+ if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
/*
@@ -1664,7 +1662,7 @@ static ssize_t smk_write_logging(struct file *file, const char __user *buf,
char temp[32];
int i;
- if (!capable(CAP_MAC_ADMIN))
+ if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
if (count >= sizeof(temp) || count == 0)
@@ -1885,7 +1883,7 @@ static ssize_t smk_write_load2(struct file *file, const char __user *buf,
/*
* Must have privilege.
*/
- if (!capable(CAP_MAC_ADMIN))
+ if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
@@ -2051,7 +2049,6 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
}
root_inode = sb->s_root->d_inode;
- root_inode->i_security = new_inode_smack(smack_known_floor.smk_known);
return 0;
}