aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/Kconfig3
-rw-r--r--security/apparmor/lsm.c4
-rw-r--r--security/integrity/ima/Kconfig58
-rw-r--r--security/integrity/ima/ima.h5
-rw-r--r--security/integrity/ima/ima_appraise.c4
-rw-r--r--security/integrity/ima/ima_main.c84
-rw-r--r--security/integrity/ima/ima_policy.c48
-rw-r--r--security/keys/dh.c6
-rw-r--r--security/loadpin/loadpin.c6
-rw-r--r--security/security.c17
-rw-r--r--security/selinux/hooks.c19
-rw-r--r--security/selinux/selinuxfs.c78
-rw-r--r--security/smack/smack_lsm.c7
-rw-r--r--security/tomoyo/tomoyo.c2
14 files changed, 253 insertions, 88 deletions
diff --git a/security/Kconfig b/security/Kconfig
index c4302067a3ad..27d8b2688f75 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -57,7 +57,7 @@ config SECURITY_NETWORK
config PAGE_TABLE_ISOLATION
bool "Remove the kernel mapping in user mode"
default y
- depends on X86_64 && !UML
+ depends on X86 && !UML
help
This feature reduces the number of hardware side channels by
ensuring that the majority of kernel addresses are not mapped
@@ -153,7 +153,6 @@ config HAVE_HARDENED_USERCOPY_ALLOCATOR
config HARDENED_USERCOPY
bool "Harden memory copies between kernel and userspace"
depends on HAVE_HARDENED_USERCOPY_ALLOCATOR
- select BUG
imply STRICT_DEVMEM
help
This option checks for obviously wrong memory regions when
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 74f17376202b..8b8b70620bbe 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -395,7 +395,7 @@ static int apparmor_inode_getattr(const struct path *path)
return common_perm_cond(OP_GETATTR, path, AA_MAY_GETATTR);
}
-static int apparmor_file_open(struct file *file, const struct cred *cred)
+static int apparmor_file_open(struct file *file)
{
struct aa_file_ctx *fctx = file_ctx(file);
struct aa_label *label;
@@ -414,7 +414,7 @@ static int apparmor_file_open(struct file *file, const struct cred *cred)
return 0;
}
- label = aa_get_newest_cred_label(cred);
+ label = aa_get_newest_cred_label(file->f_cred);
if (!unconfined(label)) {
struct inode *inode = file_inode(file);
struct path_cond cond = { inode->i_uid, inode->i_mode };
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 6a8f67714c83..004919d9bf09 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -156,6 +156,64 @@ config IMA_APPRAISE
<http://linux-ima.sourceforge.net>
If unsure, say N.
+config IMA_APPRAISE_BUILD_POLICY
+ bool "IMA build time configured policy rules"
+ depends on IMA_APPRAISE && INTEGRITY_ASYMMETRIC_KEYS
+ default n
+ help
+ This option defines an IMA appraisal policy at build time, which
+ is enforced at run time without having to specify a builtin
+ policy name on the boot command line. The build time appraisal
+ policy rules persist after loading a custom policy.
+
+ Depending on the rules configured, this policy may require kernel
+ modules, firmware, the kexec kernel image, and/or the IMA policy
+ to be signed. Unsigned files might prevent the system from
+ booting or applications from working properly.
+
+config IMA_APPRAISE_REQUIRE_FIRMWARE_SIGS
+ bool "Appraise firmware signatures"
+ depends on IMA_APPRAISE_BUILD_POLICY
+ default n
+ help
+ This option defines a policy requiring all firmware to be signed,
+ including the regulatory.db. If both this option and
+ CFG80211_REQUIRE_SIGNED_REGDB are enabled, then both signature
+ verification methods are necessary.
+
+config IMA_APPRAISE_REQUIRE_KEXEC_SIGS
+ bool "Appraise kexec kernel image signatures"
+ depends on IMA_APPRAISE_BUILD_POLICY
+ default n
+ help
+ Enabling this rule will require all kexec'ed kernel images to
+ be signed and verified by a public key on the trusted IMA
+ keyring.
+
+ Kernel image signatures can not be verified by the original
+ kexec_load syscall. Enabling this rule will prevent its
+ usage.
+
+config IMA_APPRAISE_REQUIRE_MODULE_SIGS
+ bool "Appraise kernel modules signatures"
+ depends on IMA_APPRAISE_BUILD_POLICY
+ default n
+ help
+ Enabling this rule will require all kernel modules to be signed
+ and verified by a public key on the trusted IMA keyring.
+
+ Kernel module signatures can only be verified by IMA-appraisal,
+ via the finit_module syscall. Enabling this rule will prevent
+ the usage of the init_module syscall.
+
+config IMA_APPRAISE_REQUIRE_POLICY_SIGS
+ bool "Appraise IMA policy signature"
+ depends on IMA_APPRAISE_BUILD_POLICY
+ default n
+ help
+ Enabling this rule will require the IMA policy to be signed and
+ and verified by a key on the trusted IMA keyring.
+
config IMA_APPRAISE_BOOTPARAM
bool "ima_appraise boot parameter"
depends on IMA_APPRAISE
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 354bb5716ce3..a597b2795d2d 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -232,13 +232,14 @@ int ima_policy_show(struct seq_file *m, void *v);
#define IMA_APPRAISE_MODULES 0x08
#define IMA_APPRAISE_FIRMWARE 0x10
#define IMA_APPRAISE_POLICY 0x20
+#define IMA_APPRAISE_KEXEC 0x40
#ifdef CONFIG_IMA_APPRAISE
int ima_appraise_measurement(enum ima_hooks func,
struct integrity_iint_cache *iint,
struct file *file, const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value,
- int xattr_len, int opened);
+ int xattr_len);
int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func);
void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
@@ -254,7 +255,7 @@ static inline int ima_appraise_measurement(enum ima_hooks func,
struct file *file,
const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value,
- int xattr_len, int opened)
+ int xattr_len)
{
return INTEGRITY_UNKNOWN;
}
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 8bd7a0733e51..deec1804a00a 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -212,7 +212,7 @@ int ima_appraise_measurement(enum ima_hooks func,
struct integrity_iint_cache *iint,
struct file *file, const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value,
- int xattr_len, int opened)
+ int xattr_len)
{
static const char op[] = "appraise_data";
const char *cause = "unknown";
@@ -231,7 +231,7 @@ int ima_appraise_measurement(enum ima_hooks func,
cause = iint->flags & IMA_DIGSIG_REQUIRED ?
"IMA-signature-required" : "missing-hash";
status = INTEGRITY_NOLABEL;
- if (opened & FILE_CREATED)
+ if (file->f_mode & FMODE_CREATED)
iint->flags |= IMA_NEW_FILE;
if ((iint->flags & IMA_NEW_FILE) &&
(!(iint->flags & IMA_DIGSIG_REQUIRED) ||
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index dca44cf7838e..2d31921fbda4 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -168,7 +168,7 @@ void ima_file_free(struct file *file)
static int process_measurement(struct file *file, const struct cred *cred,
u32 secid, char *buf, loff_t size, int mask,
- enum ima_hooks func, int opened)
+ enum ima_hooks func)
{
struct inode *inode = file_inode(file);
struct integrity_iint_cache *iint = NULL;
@@ -294,7 +294,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) {
inode_lock(inode);
rc = ima_appraise_measurement(func, iint, file, pathname,
- xattr_value, xattr_len, opened);
+ xattr_value, xattr_len);
inode_unlock(inode);
}
if (action & IMA_AUDIT)
@@ -338,7 +338,7 @@ int ima_file_mmap(struct file *file, unsigned long prot)
if (file && (prot & PROT_EXEC)) {
security_task_getsecid(current, &secid);
return process_measurement(file, current_cred(), secid, NULL,
- 0, MAY_EXEC, MMAP_CHECK, 0);
+ 0, MAY_EXEC, MMAP_CHECK);
}
return 0;
@@ -364,13 +364,13 @@ int ima_bprm_check(struct linux_binprm *bprm)
security_task_getsecid(current, &secid);
ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0,
- MAY_EXEC, BPRM_CHECK, 0);
+ MAY_EXEC, BPRM_CHECK);
if (ret)
return ret;
security_cred_getsecid(bprm->cred, &secid);
return process_measurement(bprm->file, bprm->cred, secid, NULL, 0,
- MAY_EXEC, CREDS_CHECK, 0);
+ MAY_EXEC, CREDS_CHECK);
}
/**
@@ -383,14 +383,14 @@ int ima_bprm_check(struct linux_binprm *bprm)
* On success return 0. On integrity appraisal error, assuming the file
* is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
*/
-int ima_file_check(struct file *file, int mask, int opened)
+int ima_file_check(struct file *file, int mask)
{
u32 secid;
security_task_getsecid(current, &secid);
return process_measurement(file, current_cred(), secid, NULL, 0,
mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
- MAY_APPEND), FILE_CHECK, opened);
+ MAY_APPEND), FILE_CHECK);
}
EXPORT_SYMBOL_GPL(ima_file_check);
@@ -429,16 +429,14 @@ void ima_post_path_mknod(struct dentry *dentry)
*/
int ima_read_file(struct file *file, enum kernel_read_file_id read_id)
{
- bool sig_enforce = is_module_sig_enforced();
-
- if (!file && read_id == READING_MODULE) {
- if (!sig_enforce && (ima_appraise & IMA_APPRAISE_MODULES) &&
- (ima_appraise & IMA_APPRAISE_ENFORCE)) {
- pr_err("impossible to appraise a module without a file descriptor. sig_enforce kernel parameter might help\n");
- return -EACCES; /* INTEGRITY_UNKNOWN */
- }
- return 0; /* We rely on module signature checking */
- }
+ /*
+ * READING_FIRMWARE_PREALLOC_BUFFER
+ *
+ * Do devices using pre-allocated memory run the risk of the
+ * firmware being accessible to the device prior to the completion
+ * of IMA's signature verification any more than when using two
+ * buffers?
+ */
return 0;
}
@@ -472,14 +470,13 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
if (!file && read_id == READING_FIRMWARE) {
if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
- (ima_appraise & IMA_APPRAISE_ENFORCE))
+ (ima_appraise & IMA_APPRAISE_ENFORCE)) {
+ pr_err("Prevent firmware loading_store.\n");
return -EACCES; /* INTEGRITY_UNKNOWN */
+ }
return 0;
}
- if (!file && read_id == READING_MODULE) /* MODULE_SIG_FORCE enabled */
- return 0;
-
/* permit signed certs */
if (!file && read_id == READING_X509_CERTIFICATE)
return 0;
@@ -493,7 +490,50 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
func = read_idmap[read_id] ?: FILE_CHECK;
security_task_getsecid(current, &secid);
return process_measurement(file, current_cred(), secid, buf, size,
- MAY_READ, func, 0);
+ MAY_READ, func);
+}
+
+/**
+ * ima_load_data - appraise decision based on policy
+ * @id: kernel load data caller identifier
+ *
+ * Callers of this LSM hook can not measure, appraise, or audit the
+ * data provided by userspace. Enforce policy rules requring a file
+ * signature (eg. kexec'ed kernel image).
+ *
+ * For permission return 0, otherwise return -EACCES.
+ */
+int ima_load_data(enum kernel_load_data_id id)
+{
+ bool sig_enforce;
+
+ if ((ima_appraise & IMA_APPRAISE_ENFORCE) != IMA_APPRAISE_ENFORCE)
+ return 0;
+
+ switch (id) {
+ case LOADING_KEXEC_IMAGE:
+ if (ima_appraise & IMA_APPRAISE_KEXEC) {
+ pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n");
+ return -EACCES; /* INTEGRITY_UNKNOWN */
+ }
+ break;
+ case LOADING_FIRMWARE:
+ if (ima_appraise & IMA_APPRAISE_FIRMWARE) {
+ pr_err("Prevent firmware sysfs fallback loading.\n");
+ return -EACCES; /* INTEGRITY_UNKNOWN */
+ }
+ break;
+ case LOADING_MODULE:
+ sig_enforce = is_module_sig_enforced();
+
+ if (!sig_enforce && (ima_appraise & IMA_APPRAISE_MODULES)) {
+ pr_err("impossible to appraise a module without a file descriptor. sig_enforce kernel parameter might help\n");
+ return -EACCES; /* INTEGRITY_UNKNOWN */
+ }
+ default:
+ break;
+ }
+ return 0;
}
static int __init init_ima(void)
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index cdcc9a7b4e24..1659abb344f9 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -49,6 +49,7 @@
int ima_policy_flag;
static int temp_ima_appraise;
+static int build_ima_appraise __ro_after_init;
#define MAX_LSM_RULES 6
enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
@@ -162,6 +163,25 @@ static struct ima_rule_entry default_appraise_rules[] __ro_after_init = {
#endif
};
+static struct ima_rule_entry build_appraise_rules[] __ro_after_init = {
+#ifdef CONFIG_IMA_APPRAISE_REQUIRE_MODULE_SIGS
+ {.action = APPRAISE, .func = MODULE_CHECK,
+ .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
+#endif
+#ifdef CONFIG_IMA_APPRAISE_REQUIRE_FIRMWARE_SIGS
+ {.action = APPRAISE, .func = FIRMWARE_CHECK,
+ .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
+#endif
+#ifdef CONFIG_IMA_APPRAISE_REQUIRE_KEXEC_SIGS
+ {.action = APPRAISE, .func = KEXEC_KERNEL_CHECK,
+ .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
+#endif
+#ifdef CONFIG_IMA_APPRAISE_REQUIRE_POLICY_SIGS
+ {.action = APPRAISE, .func = POLICY_CHECK,
+ .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
+#endif
+};
+
static struct ima_rule_entry secure_boot_rules[] __ro_after_init = {
{.action = APPRAISE, .func = MODULE_CHECK,
.flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
@@ -435,7 +455,7 @@ void ima_update_policy_flag(void)
ima_policy_flag |= entry->action;
}
- ima_appraise |= temp_ima_appraise;
+ ima_appraise |= (build_ima_appraise | temp_ima_appraise);
if (!ima_appraise)
ima_policy_flag &= ~IMA_APPRAISE;
}
@@ -448,6 +468,8 @@ static int ima_appraise_flag(enum ima_hooks func)
return IMA_APPRAISE_FIRMWARE;
else if (func == POLICY_CHECK)
return IMA_APPRAISE_POLICY;
+ else if (func == KEXEC_KERNEL_CHECK)
+ return IMA_APPRAISE_KEXEC;
return 0;
}
@@ -486,8 +508,8 @@ void __init ima_init_policy(void)
}
/*
- * Insert the appraise rules requiring file signatures, prior to
- * any other appraise rules.
+ * Insert the builtin "secure_boot" policy rules requiring file
+ * signatures, prior to any other appraise rules.
*/
for (i = 0; i < secure_boot_entries; i++) {
list_add_tail(&secure_boot_rules[i].list, &ima_default_rules);
@@ -495,6 +517,26 @@ void __init ima_init_policy(void)
ima_appraise_flag(secure_boot_rules[i].func);
}
+ /*
+ * Insert the build time appraise rules requiring file signatures
+ * for both the initial and custom policies, prior to other appraise
+ * rules.
+ */
+ for (i = 0; i < ARRAY_SIZE(build_appraise_rules); i++) {
+ struct ima_rule_entry *entry;
+
+ if (!secure_boot_entries)
+ list_add_tail(&build_appraise_rules[i].list,
+ &ima_default_rules);
+
+ entry = kmemdup(&build_appraise_rules[i], sizeof(*entry),
+ GFP_KERNEL);
+ if (entry)
+ list_add_tail(&entry->list, &ima_policy_rules);
+ build_ima_appraise |=
+ ima_appraise_flag(build_appraise_rules[i].func);
+ }
+
for (i = 0; i < appraise_entries; i++) {
list_add_tail(&default_appraise_rules[i].list,
&ima_default_rules);
diff --git a/security/keys/dh.c b/security/keys/dh.c
index f7403821db7f..b203f7758f97 100644
--- a/security/keys/dh.c
+++ b/security/keys/dh.c
@@ -142,6 +142,8 @@ static void kdf_dealloc(struct kdf_sdesc *sdesc)
* The src pointer is defined as Z || other info where Z is the shared secret
* from DH and other info is an arbitrary string (see SP800-56A section
* 5.8.1.2).
+ *
+ * 'dlen' must be a multiple of the digest size.
*/
static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen,
u8 *dst, unsigned int dlen, unsigned int zlen)
@@ -205,8 +207,8 @@ static int keyctl_dh_compute_kdf(struct kdf_sdesc *sdesc,
{
uint8_t *outbuf = NULL;
int ret;
- size_t outbuf_len = round_up(buflen,
- crypto_shash_digestsize(sdesc->shash.tfm));
+ size_t outbuf_len = roundup(buflen,
+ crypto_shash_digestsize(sdesc->shash.tfm));
outbuf = kmalloc(outbuf_len, GFP_KERNEL);
if (!outbuf) {
diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c
index 5fa191252c8f..0716af28808a 100644
--- a/security/loadpin/loadpin.c
+++ b/security/loadpin/loadpin.c
@@ -173,9 +173,15 @@ static int loadpin_read_file(struct file *file, enum kernel_read_file_id id)
return 0;
}
+static int loadpin_load_data(enum kernel_load_data_id id)
+{
+ return loadpin_read_file(NULL, (enum kernel_read_file_id) id);
+}
+
static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security),
LSM_HOOK_INIT(kernel_read_file, loadpin_read_file),
+ LSM_HOOK_INIT(kernel_load_data, loadpin_load_data),
};
void __init loadpin_add_hooks(void)
diff --git a/security/security.c b/security/security.c
index 68f46d849abe..ab4f96347ebb 100644
--- a/security/security.c
+++ b/security/security.c
@@ -118,6 +118,8 @@ static int lsm_append(char *new, char **result)
if (*result == NULL) {
*result = kstrdup(new, GFP_KERNEL);
+ if (*result == NULL)
+ return -ENOMEM;
} else {
/* Check if it is the last registered name */
if (match_last_lsm(*result, new))
@@ -970,11 +972,11 @@ int security_file_receive(struct file *file)
return call_int_hook(file_receive, 0, file);
}
-int security_file_open(struct file *file, const struct cred *cred)
+int security_file_open(struct file *file)
{
int ret;
- ret = call_int_hook(file_open, 0, file, cred);
+ ret = call_int_hook(file_open, 0, file);
if (ret)
return ret;
@@ -1056,6 +1058,17 @@ int security_kernel_post_read_file(struct file *file, char *buf, loff_t size,
}
EXPORT_SYMBOL_GPL(security_kernel_post_read_file);
+int security_kernel_load_data(enum kernel_load_data_id id)
+{
+ int ret;
+
+ ret = call_int_hook(kernel_load_data, 0, id);
+ if (ret)
+ return ret;
+ return ima_load_data(id);
+}
+EXPORT_SYMBOL_GPL(security_kernel_load_data);
+
int security_task_fix_setuid(struct cred *new, const struct cred *old,
int flags)
{
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index f78318af8254..ad9a9b8e9979 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3860,7 +3860,7 @@ static int selinux_file_receive(struct file *file)
return file_has_perm(cred, file, file_to_av(file));
}
-static int selinux_file_open(struct file *file, const struct cred *cred)
+static int selinux_file_open(struct file *file)
{
struct file_security_struct *fsec;
struct inode_security_struct *isec;
@@ -3884,7 +3884,7 @@ static int selinux_file_open(struct file *file, const struct cred *cred)
* new inode label or new policy.
* This check is not redundant - do not remove.
*/
- return file_path_has_perm(cred, file, open_file_to_av(file));
+ return file_path_has_perm(file->f_cred, file, open_file_to_av(file));
}
/* task security operations */
@@ -4071,6 +4071,20 @@ static int selinux_kernel_read_file(struct file *file,
return rc;
}
+static int selinux_kernel_load_data(enum kernel_load_data_id id)
+{
+ int rc = 0;
+
+ switch (id) {
+ case LOADING_MODULE:
+ rc = selinux_kernel_module_from_file(NULL);
+ default:
+ break;
+ }
+
+ return rc;
+}
+
static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
{
return avc_has_perm(&selinux_state,
@@ -6970,6 +6984,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
+ LSM_HOOK_INIT(kernel_load_data, selinux_kernel_load_data),
LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file),
LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 5cc9101ab79b..f3a5a138a096 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -441,22 +441,16 @@ static int sel_release_policy(struct inode *inode, struct file *filp)
static ssize_t sel_read_policy(struct file *filp, char __user *buf,
size_t count, loff_t *ppos)
{
- struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
struct policy_load_memory *plm = filp->private_data;
int ret;
- mutex_lock(&fsi->mutex);
-
ret = avc_has_perm(&selinux_state,
current_sid(), SECINITSID_SECURITY,
SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL);
if (ret)
- goto out;
+ return ret;
- ret = simple_read_from_buffer(buf, count, ppos, plm->data, plm->len);
-out:
- mutex_unlock(&fsi->mutex);
- return ret;
+ return simple_read_from_buffer(buf, count, ppos, plm->data, plm->len);
}
static vm_fault_t sel_mmap_policy_fault(struct vm_fault *vmf)
@@ -1188,25 +1182,29 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
ret = -EINVAL;
if (index >= fsi->bool_num || strcmp(name,
fsi->bool_pending_names[index]))
- goto out;
+ goto out_unlock;
ret = -ENOMEM;
page = (char *)get_zeroed_page(GFP_KERNEL);
if (!page)
- goto out;
+ goto out_unlock;
cur_enforcing = security_get_bool_value(fsi->state, index);
if (cur_enforcing < 0) {
ret = cur_enforcing;
- goto out;
+ goto out_unlock;
}
length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing,
fsi->bool_pending_values[index]);
- ret = simple_read_from_buffer(buf, count, ppos, page, length);
-out:
mutex_unlock(&fsi->mutex);
+ ret = simple_read_from_buffer(buf, count, ppos, page, length);
+out_free:
free_page((unsigned long)page);
return ret;
+
+out_unlock:
+ mutex_unlock(&fsi->mutex);
+ goto out_free;
}
static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
@@ -1219,6 +1217,17 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK;
const char *name = filep->f_path.dentry->d_name.name;
+ if (count >= PAGE_SIZE)
+ return -ENOMEM;
+
+ /* No partial writes. */
+ if (*ppos != 0)
+ return -EINVAL;
+
+ page = memdup_user_nul(buf, count);
+ if (IS_ERR(page))
+ return PTR_ERR(page);
+
mutex_lock(&fsi->mutex);
length = avc_has_perm(&selinux_state,
@@ -1233,22 +1242,6 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
fsi->bool_pending_names[index]))
goto out;
- length = -ENOMEM;
- if (count >= PAGE_SIZE)
- goto out;
-
- /* No partial writes. */
- length = -EINVAL;
- if (*ppos != 0)
- goto out;
-
- page = memdup_user_nul(buf, count);
- if (IS_ERR(page)) {
- length = PTR_ERR(page);
- page = NULL;
- goto out;
- }
-
length = -EINVAL;
if (sscanf(page, "%d", &new_value) != 1)
goto out;
@@ -1280,6 +1273,17 @@ static ssize_t sel_commit_bools_write(struct file *filep,
ssize_t length;
int new_value;
+ if (count >= PAGE_SIZE)
+ return -ENOMEM;
+
+ /* No partial writes. */
+ if (*ppos != 0)
+ return -EINVAL;
+
+ page = memdup_user_nul(buf, count);
+ if (IS_ERR(page))
+ return PTR_ERR(page);
+
mutex_lock(&fsi->mutex);
length = avc_has_perm(&selinux_state,
@@ -1289,22 +1293,6 @@ static ssize_t sel_commit_bools_write(struct file *filep,
if (length)
goto out;
- length = -ENOMEM;
- if (count >= PAGE_SIZE)
- goto out;
-
- /* No partial writes. */
- length = -EINVAL;
- if (*ppos != 0)
- goto out;
-
- page = memdup_user_nul(buf, count);
- if (IS_ERR(page)) {
- length = PTR_ERR(page);
- page = NULL;
- goto out;
- }
-
length = -EINVAL;
if (sscanf(page, "%d", &new_value) != 1)
goto out;
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 7ad226018f51..9ab8097dab7c 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1927,9 +1927,9 @@ static int smack_file_receive(struct file *file)
*
* Returns 0
*/
-static int smack_file_open(struct file *file, const struct cred *cred)
+static int smack_file_open(struct file *file)
{
- struct task_smack *tsp = cred->security;
+ struct task_smack *tsp = file->f_cred->security;
struct inode *inode = file_inode(file);
struct smk_audit_info ad;
int rc;
@@ -1937,7 +1937,7 @@ static int smack_file_open(struct file *file, const struct cred *cred)
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
smk_ad_setfield_u_fs_path(&ad, file->f_path);
rc = smk_tskacc(tsp, smk_of_inode(inode), MAY_READ, &ad);
- rc = smk_bu_credfile(cred, file, MAY_READ, rc);
+ rc = smk_bu_credfile(file->f_cred, file, MAY_READ, rc);
return rc;
}
@@ -2296,6 +2296,7 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode)
struct smack_known *skp = smk_of_task_struct(p);
isp->smk_inode = skp;
+ isp->smk_flags |= SMK_INODE_INSTANT;
}
/*
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index 213b8c593668..9f932e2d6852 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -320,7 +320,7 @@ static int tomoyo_file_fcntl(struct file *file, unsigned int cmd,
*
* Returns 0 on success, negative value otherwise.
*/
-static int tomoyo_file_open(struct file *f, const struct cred *cred)
+static int tomoyo_file_open(struct file *f)
{
int flags = f->f_flags;
/* Don't check read permission here if called from do_execve(). */