Commit bea80318 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security

Pull security subsystem updates from James Morris:
 "Apart from reordering the SELinux mmap code to ensure DAC is called
  before MAC, these are minor maintenance updates"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (23 commits)
  selinux: correctly label /proc inodes in use before the policy is loaded
  selinux: put the mmap() DAC controls before the MAC controls
  selinux: fix the output of ./scripts/get_maintainer.pl for SELinux
  evm: enable key retention service automatically
  ima: skip memory allocation for empty files
  evm: EVM does not use MD5
  ima: return d_name.name if d_path fails
  integrity: fix checkpatch errors
  ima: fix erroneous removal of security.ima xattr
  security: integrity: Use a more current logging style
  MAINTAINERS: email updates and other misc. changes
  ima: reduce memory usage when a template containing the n field is used
  ima: restore the original behavior for sending data with ima template
  Integrity: Pass commname via get_task_comm()
  fs: move i_readcount
  ima: use static const char array definitions
  security: have cap_dentry_init_security return error
  ima: new helper: file_inode(file)
  kernel: Mark function as static in kernel/seccomp.c
  capability: Use current logging styles
  ...
parents cd6362be f64410ec
...@@ -3401,7 +3401,9 @@ F: Documentation/filesystems/ext4.txt ...@@ -3401,7 +3401,9 @@ F: Documentation/filesystems/ext4.txt
F: fs/ext4/ F: fs/ext4/
Extended Verification Module (EVM) Extended Verification Module (EVM)
M: Mimi Zohar <zohar@us.ibm.com> M: Mimi Zohar <zohar@linux.vnet.ibm.com>
L: linux-ima-devel@lists.sourceforge.net
L: linux-security-module@vger.kernel.org
S: Supported S: Supported
F: security/integrity/evm/ F: security/integrity/evm/
...@@ -4423,8 +4425,11 @@ S: Maintained ...@@ -4423,8 +4425,11 @@ S: Maintained
F: drivers/ipack/ F: drivers/ipack/
INTEGRITY MEASUREMENT ARCHITECTURE (IMA) INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
M: Mimi Zohar <zohar@us.ibm.com> M: Mimi Zohar <zohar@linux.vnet.ibm.com>
M: Dmitry Kasatkin <d.kasatkin@samsung.com> M: Dmitry Kasatkin <d.kasatkin@samsung.com>
L: linux-ima-devel@lists.sourceforge.net
L: linux-ima-user@lists.sourceforge.net
L: linux-security-module@vger.kernel.org
S: Supported S: Supported
F: security/integrity/ima/ F: security/integrity/ima/
...@@ -5092,8 +5097,8 @@ F: include/keys/ ...@@ -5092,8 +5097,8 @@ F: include/keys/
F: security/keys/ F: security/keys/
KEYS-TRUSTED KEYS-TRUSTED
M: David Safford <safford@watson.ibm.com> M: David Safford <safford@us.ibm.com>
M: Mimi Zohar <zohar@us.ibm.com> M: Mimi Zohar <zohar@linux.vnet.ibm.com>
L: linux-security-module@vger.kernel.org L: linux-security-module@vger.kernel.org
L: keyrings@linux-nfs.org L: keyrings@linux-nfs.org
S: Supported S: Supported
...@@ -5103,8 +5108,8 @@ F: security/keys/trusted.c ...@@ -5103,8 +5108,8 @@ F: security/keys/trusted.c
F: security/keys/trusted.h F: security/keys/trusted.h
KEYS-ENCRYPTED KEYS-ENCRYPTED
M: Mimi Zohar <zohar@us.ibm.com> M: Mimi Zohar <zohar@linux.vnet.ibm.com>
M: David Safford <safford@watson.ibm.com> M: David Safford <safford@us.ibm.com>
L: linux-security-module@vger.kernel.org L: linux-security-module@vger.kernel.org
L: keyrings@linux-nfs.org L: keyrings@linux-nfs.org
S: Supported S: Supported
...@@ -7787,11 +7792,10 @@ M: Security Officers <security@kernel.org> ...@@ -7787,11 +7792,10 @@ M: Security Officers <security@kernel.org>
S: Supported S: Supported
SELINUX SECURITY MODULE SELINUX SECURITY MODULE
M: Paul Moore <paul@paul-moore.com>
M: Stephen Smalley <sds@tycho.nsa.gov> M: Stephen Smalley <sds@tycho.nsa.gov>
M: James Morris <james.l.morris@oracle.com>
M: Eric Paris <eparis@parisplace.org> M: Eric Paris <eparis@parisplace.org>
M: Paul Moore <paul@paul-moore.com> L: selinux@tycho.nsa.gov (moderated for non-subscribers)
L: selinux@tycho.nsa.gov (subscribers-only, general discussion)
W: http://selinuxproject.org W: http://selinuxproject.org
T: git git://git.infradead.org/users/pcmoore/selinux T: git git://git.infradead.org/users/pcmoore/selinux
S: Supported S: Supported
......
...@@ -589,6 +589,9 @@ struct inode { ...@@ -589,6 +589,9 @@ struct inode {
atomic_t i_count; atomic_t i_count;
atomic_t i_dio_count; atomic_t i_dio_count;
atomic_t i_writecount; atomic_t i_writecount;
#ifdef CONFIG_IMA
atomic_t i_readcount; /* struct files open RO */
#endif
const struct file_operations *i_fop; /* former ->i_op->default_file_ops */ const struct file_operations *i_fop; /* former ->i_op->default_file_ops */
struct file_lock *i_flock; struct file_lock *i_flock;
struct address_space i_data; struct address_space i_data;
...@@ -609,9 +612,6 @@ struct inode { ...@@ -609,9 +612,6 @@ struct inode {
struct hlist_head i_fsnotify_marks; struct hlist_head i_fsnotify_marks;
#endif #endif
#ifdef CONFIG_IMA
atomic_t i_readcount; /* struct files open RO */
#endif
void *i_private; /* fs or device private pointer */ void *i_private; /* fs or device private pointer */
}; };
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
* 30 May 2002: Cleanup, Robert M. Love <rml@tech9.net> * 30 May 2002: Cleanup, Robert M. Love <rml@tech9.net>
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/audit.h> #include <linux/audit.h>
#include <linux/capability.h> #include <linux/capability.h>
#include <linux/mm.h> #include <linux/mm.h>
...@@ -42,15 +44,10 @@ __setup("no_file_caps", file_caps_disable); ...@@ -42,15 +44,10 @@ __setup("no_file_caps", file_caps_disable);
static void warn_legacy_capability_use(void) static void warn_legacy_capability_use(void)
{ {
static int warned; char name[sizeof(current->comm)];
if (!warned) {
char name[sizeof(current->comm)]; pr_info_once("warning: `%s' uses 32-bit capabilities (legacy support in use)\n",
get_task_comm(name, current));
printk(KERN_INFO "warning: `%s' uses 32-bit capabilities"
" (legacy support in use)\n",
get_task_comm(name, current));
warned = 1;
}
} }
/* /*
...@@ -71,16 +68,10 @@ static void warn_legacy_capability_use(void) ...@@ -71,16 +68,10 @@ static void warn_legacy_capability_use(void)
static void warn_deprecated_v2(void) static void warn_deprecated_v2(void)
{ {
static int warned; char name[sizeof(current->comm)];
if (!warned) { pr_info_once("warning: `%s' uses deprecated v2 capabilities in a way that may be insecure\n",
char name[sizeof(current->comm)]; get_task_comm(name, current));
printk(KERN_INFO "warning: `%s' uses deprecated v2"
" capabilities in a way that may be insecure.\n",
get_task_comm(name, current));
warned = 1;
}
} }
/* /*
...@@ -380,7 +371,7 @@ bool has_capability_noaudit(struct task_struct *t, int cap) ...@@ -380,7 +371,7 @@ bool has_capability_noaudit(struct task_struct *t, int cap)
bool ns_capable(struct user_namespace *ns, int cap) bool ns_capable(struct user_namespace *ns, int cap)
{ {
if (unlikely(!cap_valid(cap))) { if (unlikely(!cap_valid(cap))) {
printk(KERN_CRIT "capable() called with invalid cap=%u\n", cap); pr_crit("capable() called with invalid cap=%u\n", cap);
BUG(); BUG();
} }
......
...@@ -290,7 +290,7 @@ static long seccomp_attach_filter(struct sock_fprog *fprog) ...@@ -290,7 +290,7 @@ static long seccomp_attach_filter(struct sock_fprog *fprog)
* *
* Returns 0 on success and non-zero otherwise. * Returns 0 on success and non-zero otherwise.
*/ */
long seccomp_attach_user_filter(char __user *user_filter) static long seccomp_attach_user_filter(char __user *user_filter)
{ {
struct sock_fprog fprog; struct sock_fprog fprog;
long ret = -EFAULT; long ret = -EFAULT;
......
...@@ -16,14 +16,14 @@ obj-$(CONFIG_MMU) += min_addr.o ...@@ -16,14 +16,14 @@ obj-$(CONFIG_MMU) += min_addr.o
# Object file lists # Object file lists
obj-$(CONFIG_SECURITY) += security.o capability.o obj-$(CONFIG_SECURITY) += security.o capability.o
obj-$(CONFIG_SECURITYFS) += inode.o obj-$(CONFIG_SECURITYFS) += inode.o
obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o obj-$(CONFIG_SECURITY_SELINUX) += selinux/
obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o obj-$(CONFIG_SECURITY_SMACK) += smack/
obj-$(CONFIG_AUDIT) += lsm_audit.o obj-$(CONFIG_AUDIT) += lsm_audit.o
obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/
obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/built-in.o obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/
obj-$(CONFIG_SECURITY_YAMA) += yama/built-in.o obj-$(CONFIG_SECURITY_YAMA) += yama/
obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
# Object integrity file lists # Object integrity file lists
subdir-$(CONFIG_INTEGRITY) += integrity subdir-$(CONFIG_INTEGRITY) += integrity
obj-$(CONFIG_INTEGRITY) += integrity/built-in.o obj-$(CONFIG_INTEGRITY) += integrity/
...@@ -751,7 +751,7 @@ module_param_named(enabled, apparmor_enabled, bool, S_IRUGO); ...@@ -751,7 +751,7 @@ module_param_named(enabled, apparmor_enabled, bool, S_IRUGO);
static int __init apparmor_enabled_setup(char *str) static int __init apparmor_enabled_setup(char *str)
{ {
unsigned long enabled; unsigned long enabled;
int error = strict_strtoul(str, 0, &enabled); int error = kstrtoul(str, 0, &enabled);
if (!error) if (!error)
apparmor_enabled = enabled ? 1 : 0; apparmor_enabled = enabled ? 1 : 0;
return 1; return 1;
......
...@@ -116,7 +116,7 @@ static int cap_dentry_init_security(struct dentry *dentry, int mode, ...@@ -116,7 +116,7 @@ static int cap_dentry_init_security(struct dentry *dentry, int mode,
struct qstr *name, void **ctx, struct qstr *name, void **ctx,
u32 *ctxlen) u32 *ctxlen)
{ {
return 0; return -EOPNOTSUPP;
} }
static int cap_inode_alloc_security(struct inode *inode) static int cap_inode_alloc_security(struct inode *inode)
......
...@@ -10,6 +10,6 @@ obj-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o ...@@ -10,6 +10,6 @@ obj-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
integrity-y := iint.o integrity-y := iint.o
subdir-$(CONFIG_IMA) += ima subdir-$(CONFIG_IMA) += ima
obj-$(CONFIG_IMA) += ima/built-in.o obj-$(CONFIG_IMA) += ima/
subdir-$(CONFIG_EVM) += evm subdir-$(CONFIG_EVM) += evm
obj-$(CONFIG_EVM) += evm/built-in.o obj-$(CONFIG_EVM) += evm/
config EVM config EVM
boolean "EVM support" boolean "EVM support"
depends on SECURITY && KEYS && (TRUSTED_KEYS=y || TRUSTED_KEYS=n) depends on SECURITY
select KEYS
select ENCRYPTED_KEYS
select CRYPTO_HMAC select CRYPTO_HMAC
select CRYPTO_MD5
select CRYPTO_SHA1 select CRYPTO_SHA1
select ENCRYPTED_KEYS
default n default n
help help
EVM protects a file's security extended attributes against EVM protects a file's security extended attributes against
......
...@@ -32,19 +32,19 @@ extern struct crypto_shash *hash_tfm; ...@@ -32,19 +32,19 @@ extern struct crypto_shash *hash_tfm;
/* List of EVM protected security xattrs */ /* List of EVM protected security xattrs */
extern char *evm_config_xattrnames[]; extern char *evm_config_xattrnames[];
extern int evm_init_key(void); int evm_init_key(void);
extern int evm_update_evmxattr(struct dentry *dentry, int evm_update_evmxattr(struct dentry *dentry,
const char *req_xattr_name, const char *req_xattr_name,
const char *req_xattr_value, const char *req_xattr_value,
size_t req_xattr_value_len); size_t req_xattr_value_len);
extern int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name, int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
const char *req_xattr_value, const char *req_xattr_value,
size_t req_xattr_value_len, char *digest); size_t req_xattr_value_len, char *digest);
extern int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name, int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
const char *req_xattr_value, const char *req_xattr_value,
size_t req_xattr_value_len, char *digest); size_t req_xattr_value_len, char *digest);
extern int evm_init_hmac(struct inode *inode, const struct xattr *xattr, int evm_init_hmac(struct inode *inode, const struct xattr *xattr,
char *hmac_val); char *hmac_val);
extern int evm_init_secfs(void); int evm_init_secfs(void);
#endif #endif
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
* Using root's kernel master key (kmk), calculate the HMAC * Using root's kernel master key (kmk), calculate the HMAC
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h> #include <linux/module.h>
#include <linux/crypto.h> #include <linux/crypto.h>
#include <linux/xattr.h> #include <linux/xattr.h>
...@@ -103,13 +105,13 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode, ...@@ -103,13 +105,13 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
umode_t mode; umode_t mode;
} hmac_misc; } hmac_misc;
memset(&hmac_misc, 0, sizeof hmac_misc); memset(&hmac_misc, 0, sizeof(hmac_misc));
hmac_misc.ino = inode->i_ino; hmac_misc.ino = inode->i_ino;
hmac_misc.generation = inode->i_generation; hmac_misc.generation = inode->i_generation;
hmac_misc.uid = from_kuid(&init_user_ns, inode->i_uid); hmac_misc.uid = from_kuid(&init_user_ns, inode->i_uid);
hmac_misc.gid = from_kgid(&init_user_ns, inode->i_gid); hmac_misc.gid = from_kgid(&init_user_ns, inode->i_gid);
hmac_misc.mode = inode->i_mode; hmac_misc.mode = inode->i_mode;
crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof hmac_misc); crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof(hmac_misc));
if (evm_hmac_version > 1) if (evm_hmac_version > 1)
crypto_shash_update(desc, inode->i_sb->s_uuid, crypto_shash_update(desc, inode->i_sb->s_uuid,
sizeof(inode->i_sb->s_uuid)); sizeof(inode->i_sb->s_uuid));
...@@ -221,7 +223,7 @@ int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr, ...@@ -221,7 +223,7 @@ int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr,
desc = init_desc(EVM_XATTR_HMAC); desc = init_desc(EVM_XATTR_HMAC);
if (IS_ERR(desc)) { if (IS_ERR(desc)) {
printk(KERN_INFO "init_desc failed\n"); pr_info("init_desc failed\n");
return PTR_ERR(desc); return PTR_ERR(desc);
} }
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
* evm_inode_removexattr, and evm_verifyxattr * evm_inode_removexattr, and evm_verifyxattr
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h> #include <linux/module.h>
#include <linux/crypto.h> #include <linux/crypto.h>
#include <linux/audit.h> #include <linux/audit.h>
...@@ -432,7 +434,7 @@ static int __init init_evm(void) ...@@ -432,7 +434,7 @@ static int __init init_evm(void)
error = evm_init_secfs(); error = evm_init_secfs();
if (error < 0) { if (error < 0) {
printk(KERN_INFO "EVM: Error registering secfs\n"); pr_info("Error registering secfs\n");
goto err; goto err;
} }
...@@ -449,7 +451,7 @@ static int __init evm_display_config(void) ...@@ -449,7 +451,7 @@ static int __init evm_display_config(void)
char **xattrname; char **xattrname;
for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++)
printk(KERN_INFO "EVM: %s\n", *xattrname); pr_info("%s\n", *xattrname);
return 0; return 0;
} }
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
* - Get the key and enable EVM * - Get the key and enable EVM
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/module.h> #include <linux/module.h>
#include "evm.h" #include "evm.h"
...@@ -79,9 +81,9 @@ static ssize_t evm_write_key(struct file *file, const char __user *buf, ...@@ -79,9 +81,9 @@ static ssize_t evm_write_key(struct file *file, const char __user *buf,
error = evm_init_key(); error = evm_init_key();
if (!error) { if (!error) {
evm_initialized = 1; evm_initialized = 1;
pr_info("EVM: initialized\n"); pr_info("initialized\n");
} else } else
pr_err("EVM: initialization failed\n"); pr_err("initialization failed\n");
return count; return count;
} }
......
...@@ -151,7 +151,7 @@ static void init_once(void *foo) ...@@ -151,7 +151,7 @@ static void init_once(void *foo)
{ {
struct integrity_iint_cache *iint = foo; struct integrity_iint_cache *iint = foo;
memset(iint, 0, sizeof *iint); memset(iint, 0, sizeof(*iint));
iint->version = 0; iint->version = 0;
iint->flags = 0UL; iint->flags = 0UL;
iint->ima_file_status = INTEGRITY_UNKNOWN; iint->ima_file_status = INTEGRITY_UNKNOWN;
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include "../integrity.h" #include "../integrity.h"
enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_BINARY_NO_FIELD_LEN, enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_BINARY_NO_FIELD_LEN,
IMA_SHOW_ASCII }; IMA_SHOW_BINARY_OLD_STRING_FMT, IMA_SHOW_ASCII };
enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 }; enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
/* digest size for IMA, fits SHA1 or MD5 */ /* digest size for IMA, fits SHA1 or MD5 */
......
...@@ -92,8 +92,8 @@ int ima_store_template(struct ima_template_entry *entry, ...@@ -92,8 +92,8 @@ int ima_store_template(struct ima_template_entry *entry,
int violation, struct inode *inode, int violation, struct inode *inode,
const unsigned char *filename) const unsigned char *filename)
{ {
const char *op = "add_template_measure"; static const char op[] = "add_template_measure";
const char *audit_cause = "hashing_error"; static const char audit_cause[] = "hashing_error";
char *template_name = entry->template_desc->name; char *template_name = entry->template_desc->name;
int result; int result;
struct { struct {
...@@ -132,7 +132,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename, ...@@ -132,7 +132,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
const char *op, const char *cause) const char *op, const char *cause)
{ {
struct ima_template_entry *entry; struct ima_template_entry *entry;
struct inode *inode = file->f_dentry->d_inode; struct inode *inode = file_inode(file);
int violation = 1; int violation = 1;
int result; int result;
...@@ -160,10 +160,10 @@ void ima_add_violation(struct file *file, const unsigned char *filename, ...@@ -160,10 +160,10 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
* @function: calling function (FILE_CHECK, BPRM_CHECK, MMAP_CHECK, MODULE_CHECK) * @function: calling function (FILE_CHECK, BPRM_CHECK, MMAP_CHECK, MODULE_CHECK)
* *
* The policy is defined in terms of keypairs: * The policy is defined in terms of keypairs:
* subj=, obj=, type=, func=, mask=, fsmagic= * subj=, obj=, type=, func=, mask=, fsmagic=
* subj,obj, and type: are LSM specific. * subj,obj, and type: are LSM specific.
* func: FILE_CHECK | BPRM_CHECK | MMAP_CHECK | MODULE_CHECK * func: FILE_CHECK | BPRM_CHECK | MMAP_CHECK | MODULE_CHECK
* mask: contains the permission mask * mask: contains the permission mask
* fsmagic: hex value * fsmagic: hex value
* *
* Returns IMA_MEASURE, IMA_APPRAISE mask. * Returns IMA_MEASURE, IMA_APPRAISE mask.
...@@ -248,7 +248,7 @@ int ima_collect_measurement(struct integrity_iint_cache *iint, ...@@ -248,7 +248,7 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
* *
* We only get here if the inode has not already been measured, * We only get here if the inode has not already been measured,
* but the measurement could already exist: * but the measurement could already exist:
* - multiple copies of the same file on either the same or * - multiple copies of the same file on either the same or
* different filesystems. * different filesystems.
* - the inode was previously flushed as well as the iint info, * - the inode was previously flushed as well as the iint info,
* containing the hashing info. * containing the hashing info.
...@@ -260,8 +260,8 @@ void ima_store_measurement(struct integrity_iint_cache *iint, ...@@ -260,8 +260,8 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
struct evm_ima_xattr_data *xattr_value, struct evm_ima_xattr_data *xattr_value,
int xattr_len) int xattr_len)
{ {
const char *op = "add_template_measure"; static const char op[] = "add_template_measure";
const char *audit_cause = "ENOMEM"; static const char audit_cause[] = "ENOMEM";
int result = -ENOMEM; int result = -ENOMEM;
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
struct ima_template_entry *entry; struct ima_template_entry *entry;
...@@ -332,5 +332,5 @@ const char *ima_d_path(struct path *path, char **pathbuf) ...@@ -332,5 +332,5 @@ const char *ima_d_path(struct path *path, char **pathbuf)
pathname = NULL; pathname = NULL;
} }
} }
return pathname; return pathname ?: (const char *)path->dentry->d_name.name;
} }
...@@ -177,11 +177,11 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, ...@@ -177,11 +177,11 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
struct evm_ima_xattr_data *xattr_value, struct evm_ima_xattr_data *xattr_value,
int xattr_len) int xattr_len)
{ {
static const char op[] = "appraise_data";
char *cause = "unknown";
struct dentry *dentry = file->f_dentry; struct dentry *dentry = file->f_dentry;
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
enum integrity_status status = INTEGRITY_UNKNOWN; enum integrity_status status = INTEGRITY_UNKNOWN;
const char *op = "appraise_data";
char *cause = "unknown";
int rc = xattr_len, hash_start = 0; int rc = xattr_len, hash_start = 0;
if (!ima_appraise) if (!ima_appraise)
......
...@@ -10,9 +10,11 @@ ...@@ -10,9 +10,11 @@
* the Free Software Foundation, version 2 of the License. * the Free Software Foundation, version 2 of the License.
* *
* File: ima_crypto.c * File: ima_crypto.c
* Calculates md5/sha1 file hash, template hash, boot-aggreate hash * Calculates md5/sha1 file hash, template hash, boot-aggreate hash
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/crypto.h> #include <linux/crypto.h>
...@@ -85,16 +87,20 @@ static int ima_calc_file_hash_tfm(struct file *file, ...@@ -85,16 +87,20 @@ static int ima_calc_file_hash_tfm(struct file *file,
if (rc != 0) if (rc != 0)
return rc; return rc;
rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL); i_size = i_size_read(file_inode(file));
if (!rbuf) {
rc = -ENOMEM; if (i_size == 0)
goto out; goto out;
}
rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!rbuf)
return -ENOMEM;
if (!(file->f_mode & FMODE_READ)) { if (!(file->f_mode & FMODE_READ)) {
file->f_mode |= FMODE_READ; file->f_mode |= FMODE_READ;
read = 1; read = 1;
} }
i_size = i_size_read(file_inode(file));
while (offset < i_size) { while (offset < i_size) {
int rbuf_len; int rbuf_len;
...@@ -111,12 +117,12 @@ static int ima_calc_file_hash_tfm(struct file *file, ...@@ -111,12 +117,12 @@ static int ima_calc_file_hash_tfm(struct file *file,
if (rc) if (rc)
break; break;
} }
kfree(rbuf);
if (!rc)
rc = crypto_shash_final(&desc.shash, hash->digest);
if (read) if (read)
file->f_mode &= ~FMODE_READ; file->f_mode &= ~FMODE_READ;
kfree(rbuf);
out: out:
if (!rc)
rc = crypto_shash_final(&desc.shash, hash->digest);
return rc; return rc;
} }
...@@ -161,15 +167,22 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, ...@@ -161,15 +167,22 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data,
return rc; return rc;
for (i = 0; i < num_fields; i++) { for (i = 0; i < num_fields; i++) {
u8 buffer[IMA_EVENT_NAME_LEN_MAX + 1] = { 0 };
u8 *data_to_hash = field_data[i].data;
u32 datalen = field_data[i].len;
if (strcmp(td->name, IMA_TEMPLATE_IMA_NAME) != 0) { if (strcmp(td->name, IMA_TEMPLATE_IMA_NAME) != 0) {
rc = crypto_shash_update(&desc.shash, rc = crypto_shash_update(&desc.shash,
(const u8 *) &field_data[i].len, (const u8 *) &field_data[i].len,
sizeof(field_data[i].len)); sizeof(field_data[i].len));
if (rc) if (rc)
break; break;
} else if (strcmp(td->fields[i]->field_id, "n") == 0) {
memcpy(buffer, data_to_hash, datalen);
data_to_hash = buffer;
datalen = IMA_EVENT_NAME_LEN_MAX + 1;
} }
rc = crypto_shash_update(&desc.shash, field_data[i].data, rc = crypto_shash_update(&desc.shash, data_to_hash, datalen);
field_data[i].len);
if (rc) if (rc)
break; break;
} }
...@@ -205,7 +218,7 @@ static void __init ima_pcrread(int idx, u8 *pcr) ...@@ -205,7 +218,7 @@ static void __init ima_pcrread(int idx, u8 *pcr)
return; return;
if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0) if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0)
pr_err("IMA: Error Communicating to TPM chip\n"); pr_err("Error Communicating to TPM chip\n");
} }
/* /*
......
...@@ -133,14 +133,14 @@ static int ima_measurements_show(struct seq_file *m, void *v) ...@@ -133,14 +133,14 @@ static int ima_measurements_show(struct seq_file *m, void *v)
* PCR used is always the same (config option) in * PCR used is always the same (config option) in
* little-endian format * little-endian format
*/ */
ima_putc(m, &pcr, sizeof pcr); ima_putc(m, &pcr, sizeof(pcr));
/* 2nd: template digest */ /* 2nd: template digest */
ima_putc(m, e->digest, TPM_DIGEST_SIZE); ima_putc(m, e->digest, TPM_DIGEST_SIZE);
/* 3rd: template name size */ /* 3rd: template name size */
namelen = strlen(e->template_desc->name); namelen = strlen(e->template_desc->name);
ima_putc(m, &namelen, sizeof namelen); ima_putc(m, &namelen, sizeof(namelen));
/* 4th: template name */ /* 4th: template name */
ima_putc(m, e->template_desc->name, namelen); ima_putc(m, e->template_desc->name, namelen);
...@@ -160,6 +160,8 @@ static int ima_measurements_show(struct seq_file *m, void *v) ...@@ -160,6 +160,8 @@ static int ima_measurements_show(struct seq_file *m, void *v)
if (is_ima_template && strcmp(field->field_id, "d") == 0) if (is_ima_template && strcmp(field->field_id, "d") == 0)
show = IMA_SHOW_BINARY_NO_FIELD_LEN; show = IMA_SHOW_BINARY_NO_FIELD_LEN;
if (is_ima_template && strcmp(field->field_id, "n") == 0)
show = IMA_SHOW_BINARY_OLD_STRING_FMT;
field->field_show(m, show, &e->template_data[i]); field->field_show(m, show, &e->template_data[i]);
} }
return 0; return 0;
...@@ -290,7 +292,7 @@ static atomic_t policy_opencount = ATOMIC_INIT(1); ...@@ -290,7 +292,7 @@ static atomic_t policy_opencount = ATOMIC_INIT(1);
/* /*
* ima_open_policy: sequentialize access to the policy file * ima_open_policy: sequentialize access to the policy file
*/ */
static int ima_open_policy(struct inode * inode, struct file * filp) static int ima_open_policy(struct inode *inode, struct file *filp)
{ {
/* No point in being allowed to open it if you aren't going to write */ /* No point in being allowed to open it if you aren't going to write */
if (!(filp->f_flags & O_WRONLY)) if (!(filp->f_flags & O_WRONLY))
......
...@@ -14,6 +14,9 @@ ...@@ -14,6 +14,9 @@
* File: ima_init.c * File: ima_init.c
* initialization and cleanup functions * initialization and cleanup functions
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h> #include <linux/module.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -42,10 +45,10 @@ int ima_used_chip; ...@@ -42,10 +45,10 @@ int ima_used_chip;
*/ */
static void __init ima_add_boot_aggregate(void) static void __init ima_add_boot_aggregate(void)
{ {
static const char op[] = "add_boot_aggregate";
const char *audit_cause = "ENOMEM";
struct ima_template_entry *entry; struct ima_template_entry *entry;
struct integrity_iint_cache tmp_iint, *iint = &tmp_iint; struct integrity_iint_cache tmp_iint, *iint = &tmp_iint;
const char *op = "add_boot_aggregate";
const char *audit_cause = "ENOMEM";
int result = -ENOMEM; int result = -ENOMEM;
int violation = 0; int violation = 0;
struct { struct {
...@@ -93,7 +96,7 @@ int __init ima_init(void) ...@@ -93,7 +96,7 @@ int __init ima_init(void)
ima_used_chip = 1; ima_used_chip = 1;
if (!ima_used_chip) if (!ima_used_chip)
pr_info("IMA: No TPM chip found, activating TPM-bypass!\n"); pr_info("No TPM chip found, activating TPM-bypass!\n");
rc = ima_init_crypto(); rc = ima_init_crypto();
if (rc) if (rc)
......
...@@ -71,15 +71,14 @@ __setup("ima_hash=", hash_setup); ...@@ -71,15 +71,14 @@ __setup("ima_hash=", hash_setup);
* ima_rdwr_violation_check * ima_rdwr_violation_check
* *
* Only invalidate the PCR for measured files: * Only invalidate the PCR for measured files:
* - Opening a file for write when already open for read, * - Opening a file for write when already open for read,
* results in a time of measure, time of use (ToMToU) error. * results in a time of measure, time of use (ToMToU) error.
* - Opening a file for read when already open for write, * - Opening a file for read when already open for write,
* could result in a file measurement error. * could result in a file measurement error.
* *
*/ */
static void ima_rdwr_violation_check(struct file *file) static void ima_rdwr_violation_check(struct file *file)
{ {
struct dentry *dentry = file->f_path.dentry;
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
fmode_t mode = file->f_mode; fmode_t mode = file->f_mode;
int must_measure; int must_measure;
...@@ -111,8 +110,6 @@ static void ima_rdwr_violation_check(struct file *file) ...@@ -111,8 +110,6 @@ static void ima_rdwr_violation_check(struct file *file)
return; return;
pathname = ima_d_path(&file->f_path, &pathbuf); pathname = ima_d_path(&file->f_path, &pathbuf);
if (!pathname || strlen(pathname) > IMA_EVENT_NAME_LEN_MAX)
pathname = dentry->d_name.name;
if (send_tomtou) if (send_tomtou)
ima_add_violation(file, pathname, "invalid_pcr", "ToMToU"); ima_add_violation(file, pathname, "invalid_pcr", "ToMToU");
...@@ -220,9 +217,7 @@ static int process_measurement(struct file *file, const char *filename, ...@@ -220,9 +217,7 @@ static int process_measurement(struct file *file, const char *filename,
if (rc != 0) if (rc != 0)
goto out_digsig; goto out_digsig;
pathname = !filename ? ima_d_path(&file->f_path, &pathbuf) : filename; pathname = filename ?: ima_d_path(&file->f_path, &pathbuf);
if (!pathname)
pathname = (const char *)file->f_dentry->d_name.name;
if (action & IMA_MEASURE) if (action & IMA_MEASURE)
ima_store_measurement(iint, file, pathname, ima_store_measurement(iint, file, pathname,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* the Free Software Foundation, version 2 of the License. * the Free Software Foundation, version 2 of the License.
* *
* ima_policy.c * ima_policy.c
* - initialize default measure policy rules * - initialize default measure policy rules
* *
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -21,8 +21,8 @@ ...@@ -21,8 +21,8 @@
#include "ima.h" #include "ima.h"
/* flags definitions */ /* flags definitions */
#define IMA_FUNC 0x0001 #define IMA_FUNC 0x0001
#define IMA_MASK 0x0002 #define IMA_MASK 0x0002
#define IMA_FSMAGIC 0x0004 #define IMA_FSMAGIC 0x0004
#define IMA_UID 0x0008 #define IMA_UID 0x0008
#define IMA_FOWNER 0x0010 #define IMA_FOWNER 0x0010
...@@ -69,35 +69,35 @@ struct ima_rule_entry { ...@@ -69,35 +69,35 @@ struct ima_rule_entry {
* and running executables. * and running executables.
*/ */
static struct ima_rule_entry default_rules[] = { static struct ima_rule_entry default_rules[] = {
{.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE, .fsmagic = DEBUGFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE, .fsmagic = TMPFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_MEASURE,.fsmagic = DEVPTS_SUPER_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 = BINFMTFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_MEASURE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
{.action = MEASURE,.func = MMAP_CHECK,.mask = MAY_EXEC, {.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC,
.flags = IMA_FUNC | IMA_MASK}, .flags = IMA_FUNC | IMA_MASK},
{.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC, {.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC,
.flags = IMA_FUNC | IMA_MASK}, .flags = IMA_FUNC | IMA_MASK},
{.action = MEASURE,.func = FILE_CHECK,.mask = MAY_READ,.uid = GLOBAL_ROOT_UID, {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ, .uid = GLOBAL_ROOT_UID,
.flags = IMA_FUNC | IMA_MASK | IMA_UID}, .flags = IMA_FUNC | IMA_MASK | IMA_UID},
{.action = MEASURE,.func = MODULE_CHECK, .flags = IMA_FUNC}, {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
}; };
static struct ima_rule_entry default_appraise_rules[] = { static struct ima_rule_entry default_appraise_rules[] = {
{.action = DONT_APPRAISE,.fsmagic = PROC_SUPER_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_APPRAISE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_APPRAISE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_APPRAISE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_APPRAISE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_APPRAISE, .fsmagic = DEBUGFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_APPRAISE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_APPRAISE, .fsmagic = TMPFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_APPRAISE,.fsmagic = RAMFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_APPRAISE, .fsmagic = RAMFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_APPRAISE,.fsmagic = DEVPTS_SUPER_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_APPRAISE, .fsmagic = DEVPTS_SUPER_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_APPRAISE,.fsmagic = BINFMTFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_APPRAISE, .fsmagic = BINFMTFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_APPRAISE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_APPRAISE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_APPRAISE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_APPRAISE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_APPRAISE,.fsmagic = CGROUP_SUPER_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC},
{.action = APPRAISE,.fowner = GLOBAL_ROOT_UID,.flags = IMA_FOWNER}, {.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .flags = IMA_FOWNER},
}; };
static LIST_HEAD(ima_default_rules); static LIST_HEAD(ima_default_rules);
...@@ -122,12 +122,12 @@ static int __init default_appraise_policy_setup(char *str) ...@@ -122,12 +122,12 @@ static int __init default_appraise_policy_setup(char *str)
} }
__setup("ima_appraise_tcb", default_appraise_policy_setup); __setup("ima_appraise_tcb", default_appraise_policy_setup);
/* /*
* Although the IMA policy does not change, the LSM policy can be * Although the IMA policy does not change, the LSM policy can be
* reloaded, leaving the IMA LSM based rules referring to the old, * reloaded, leaving the IMA LSM based rules referring to the old,
* stale LSM policy. * stale LSM policy.
* *
* Update the IMA LSM based rules to reflect the reloaded LSM policy. * Update the IMA LSM based rules to reflect the reloaded LSM policy.
* We assume the rules still exist; and BUG_ON() if they don't. * We assume the rules still exist; and BUG_ON() if they don't.
*/ */
static void ima_lsm_update_rules(void) static void ima_lsm_update_rules(void)
...@@ -167,9 +167,11 @@ static bool ima_match_rules(struct ima_rule_entry *rule, ...@@ -167,9 +167,11 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
const struct cred *cred = current_cred(); const struct cred *cred = current_cred();
int i; int i;
if ((rule->flags & IMA_FUNC) && rule->func != func) if ((rule->flags & IMA_FUNC) &&
(rule->func != func && func != POST_SETATTR))
return false; return false;
if ((rule->flags & IMA_MASK) && rule->mask != mask) if ((rule->flags & IMA_MASK) &&
(rule->mask != mask && func != POST_SETATTR))
return false; return false;
if ((rule->flags & IMA_FSMAGIC) if ((rule->flags & IMA_FSMAGIC)
&& rule->fsmagic != inode->i_sb->s_magic) && rule->fsmagic != inode->i_sb->s_magic)
...@@ -216,7 +218,7 @@ static bool ima_match_rules(struct ima_rule_entry *rule, ...@@ -216,7 +218,7 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
retried = 1; retried = 1;
ima_lsm_update_rules(); ima_lsm_update_rules();
goto retry; goto retry;
} }
if (!rc) if (!rc)
return false; return false;
} }
...@@ -232,7 +234,7 @@ static int get_subaction(struct ima_rule_entry *rule, int func) ...@@ -232,7 +234,7 @@ static int get_subaction(struct ima_rule_entry *rule, int func)
if (!(rule->flags & IMA_FUNC)) if (!(rule->flags & IMA_FUNC))
return IMA_FILE_APPRAISE; return IMA_FILE_APPRAISE;
switch(func) { switch (func) {
case MMAP_CHECK: case MMAP_CHECK:
return IMA_MMAP_APPRAISE; return IMA_MMAP_APPRAISE;
case BPRM_CHECK: case BPRM_CHECK:
...@@ -304,7 +306,7 @@ void __init ima_init_policy(void) ...@@ -304,7 +306,7 @@ void __init ima_init_policy(void)
measure_entries = ima_use_tcb ? ARRAY_SIZE(default_rules) : 0; measure_entries = ima_use_tcb ? ARRAY_SIZE(default_rules) : 0;
appraise_entries = ima_use_appraise_tcb ? appraise_entries = ima_use_appraise_tcb ?
ARRAY_SIZE(default_appraise_rules) : 0; ARRAY_SIZE(default_appraise_rules) : 0;
for (i = 0; i < measure_entries + appraise_entries; i++) { for (i = 0; i < measure_entries + appraise_entries; i++) {
if (i < measure_entries) if (i < measure_entries)
list_add_tail(&default_rules[i].list, list_add_tail(&default_rules[i].list,
...@@ -329,7 +331,7 @@ void __init ima_init_policy(void) ...@@ -329,7 +331,7 @@ void __init ima_init_policy(void)
*/ */
void ima_update_policy(void) void ima_update_policy(void)
{ {
const char *op = "policy_update"; static const char op[] = "policy_update";
const char *cause = "already exists"; const char *cause = "already exists";
int result = 1; int result = 1;
int audit_info = 0; int audit_info = 0;
...@@ -520,8 +522,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) ...@@ -520,8 +522,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
break; break;
} }
result = strict_strtoul(args[0].from, 16, result = kstrtoul(args[0].from, 16, &entry->fsmagic);
&entry->fsmagic);
if (!result) if (!result)
entry->flags |= IMA_FSMAGIC; entry->flags |= IMA_FSMAGIC;
break; break;
...@@ -547,7 +548,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) ...@@ -547,7 +548,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
break; break;
} }
result = strict_strtoul(args[0].from, 10, &lnum); result = kstrtoul(args[0].from, 10, &lnum);
if (!result) { if (!result) {
entry->uid = make_kuid(current_user_ns(), (uid_t)lnum); entry->uid = make_kuid(current_user_ns(), (uid_t)lnum);
if (!uid_valid(entry->uid) || (((uid_t)lnum) != lnum)) if (!uid_valid(entry->uid) || (((uid_t)lnum) != lnum))
...@@ -564,7 +565,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) ...@@ -564,7 +565,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
break; break;
} }
result = strict_strtoul(args[0].from, 10, &lnum); result = kstrtoul(args[0].from, 10, &lnum);
if (!result) { if (!result) {
entry->fowner = make_kuid(current_user_ns(), (uid_t)lnum); entry->fowner = make_kuid(current_user_ns(), (uid_t)lnum);
if (!uid_valid(entry->fowner) || (((uid_t)lnum) != lnum)) if (!uid_valid(entry->fowner) || (((uid_t)lnum) != lnum))
...@@ -645,7 +646,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) ...@@ -645,7 +646,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
*/ */
ssize_t ima_parse_add_rule(char *rule) ssize_t ima_parse_add_rule(char *rule)
{ {
const char *op = "update_policy"; static const char op[] = "update_policy";
char *p; char *p;
struct ima_rule_entry *entry; struct ima_rule_entry *entry;
ssize_t result, len; ssize_t result, len;
......
...@@ -18,6 +18,9 @@ ...@@ -18,6 +18,9 @@
* The measurement list is append-only. No entry is * The measurement list is append-only. No entry is
* ever removed or changed during the boot-cycle. * ever removed or changed during the boot-cycle.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h> #include <linux/module.h>
#include <linux/rculist.h> #include <linux/rculist.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -72,7 +75,7 @@ static int ima_add_digest_entry(struct ima_template_entry *entry) ...@@ -72,7 +75,7 @@ static int ima_add_digest_entry(struct ima_template_entry *entry)
qe = kmalloc(sizeof(*qe), GFP_KERNEL); qe = kmalloc(sizeof(*qe), GFP_KERNEL);
if (qe == NULL) { if (qe == NULL) {
pr_err("IMA: OUT OF MEMORY ERROR creating queue entry.\n"); pr_err("OUT OF MEMORY ERROR creating queue entry\n");
return -ENOMEM; return -ENOMEM;
} }
qe->entry = entry; qe->entry = entry;
...@@ -95,8 +98,7 @@ static int ima_pcr_extend(const u8 *hash) ...@@ -95,8 +98,7 @@ static int ima_pcr_extend(const u8 *hash)
result = tpm_pcr_extend(TPM_ANY_NUM, CONFIG_IMA_MEASURE_PCR_IDX, hash); result = tpm_pcr_extend(TPM_ANY_NUM, CONFIG_IMA_MEASURE_PCR_IDX, hash);
if (result != 0) if (result != 0)
pr_err("IMA: Error Communicating to TPM chip, result: %d\n", pr_err("Error Communicating to TPM chip, result: %d\n", result);
result);
return result; return result;
} }
...@@ -115,7 +117,7 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation, ...@@ -115,7 +117,7 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
mutex_lock(&ima_extend_list_mutex); mutex_lock(&ima_extend_list_mutex);
if (!violation) { if (!violation) {
memcpy(digest, entry->digest, sizeof digest); memcpy(digest, entry->digest, sizeof(digest));
if (ima_lookup_digest_entry(digest)) { if (ima_lookup_digest_entry(digest)) {
audit_cause = "hash_exists"; audit_cause = "hash_exists";
result = -EEXIST; result = -EEXIST;
...@@ -131,7 +133,7 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation, ...@@ -131,7 +133,7 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
} }
if (violation) /* invalidate pcr */ if (violation) /* invalidate pcr */
memset(digest, 0xff, sizeof digest); memset(digest, 0xff, sizeof(digest));
tpmresult = ima_pcr_extend(digest); tpmresult = ima_pcr_extend(digest);
if (tpmresult != 0) { if (tpmresult != 0) {
......
...@@ -12,6 +12,9 @@ ...@@ -12,6 +12,9 @@
* File: ima_template.c * File: ima_template.c
* Helpers to manage template descriptors. * Helpers to manage template descriptors.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <crypto/hash_info.h> #include <crypto/hash_info.h>
#include "ima.h" #include "ima.h"
...@@ -19,20 +22,20 @@ ...@@ -19,20 +22,20 @@
static struct ima_template_desc defined_templates[] = { static struct ima_template_desc defined_templates[] = {
{.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT}, {.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT},
{.name = "ima-ng",.fmt = "d-ng|n-ng"}, {.name = "ima-ng", .fmt = "d-ng|n-ng"},
{.name = "ima-sig",.fmt = "d-ng|n-ng|sig"}, {.name = "ima-sig", .fmt = "d-ng|n-ng|sig"},
}; };
static struct ima_template_field supported_fields[] = { static struct ima_template_field supported_fields[] = {
{.field_id = "d",.field_init = ima_eventdigest_init, {.field_id = "d", .field_init = ima_eventdigest_init,
.field_show = ima_show_template_digest}, .field_show = ima_show_template_digest},
{.field_id = "n",.field_init = ima_eventname_init, {.field_id = "n", .field_init = ima_eventname_init,
.field_show = ima_show_template_string}, .field_show = ima_show_template_string},
{.field_id = "d-ng",.field_init = ima_eventdigest_ng_init, {.field_id = "d-ng", .field_init = ima_eventdigest_ng_init,
.field_show = ima_show_template_digest_ng}, .field_show = ima_show_template_digest_ng},
{.field_id = "n-ng",.field_init = ima_eventname_ng_init, {.field_id = "n-ng", .field_init = ima_eventname_ng_init,
.field_show = ima_show_template_string}, .field_show = ima_show_template_string},
{.field_id = "sig",.field_init = ima_eventsig_init, {.field_id = "sig", .field_init = ima_eventsig_init,
.field_show = ima_show_template_sig}, .field_show = ima_show_template_sig},
}; };
...@@ -58,7 +61,7 @@ static int __init ima_template_setup(char *str) ...@@ -58,7 +61,7 @@ static int __init ima_template_setup(char *str)
*/ */
if (template_len == 3 && strcmp(str, IMA_TEMPLATE_IMA_NAME) == 0 && if (template_len == 3 && strcmp(str, IMA_TEMPLATE_IMA_NAME) == 0 &&
ima_hash_algo != HASH_ALGO_SHA1 && ima_hash_algo != HASH_ALGO_MD5) { ima_hash_algo != HASH_ALGO_SHA1 && ima_hash_algo != HASH_ALGO_MD5) {
pr_err("IMA: template does not support hash alg\n"); pr_err("template does not support hash alg\n");
return 1; return 1;
} }
......
...@@ -27,7 +27,6 @@ static bool ima_template_hash_algo_allowed(u8 algo) ...@@ -27,7 +27,6 @@ static bool ima_template_hash_algo_allowed(u8 algo)
enum data_formats { enum data_formats {
DATA_FMT_DIGEST = 0, DATA_FMT_DIGEST = 0,
DATA_FMT_DIGEST_WITH_ALGO, DATA_FMT_DIGEST_WITH_ALGO,
DATA_FMT_EVENT_NAME,
DATA_FMT_STRING, DATA_FMT_STRING,
DATA_FMT_HEX DATA_FMT_HEX
}; };
...@@ -37,18 +36,10 @@ static int ima_write_template_field_data(const void *data, const u32 datalen, ...@@ -37,18 +36,10 @@ static int ima_write_template_field_data(const void *data, const u32 datalen,
struct ima_field_data *field_data) struct ima_field_data *field_data)
{ {
u8 *buf, *buf_ptr; u8 *buf, *buf_ptr;
u32 buflen; u32 buflen = datalen;
switch (datafmt) { if (datafmt == DATA_FMT_STRING)
case DATA_FMT_EVENT_NAME:
buflen = IMA_EVENT_NAME_LEN_MAX + 1;
break;
case DATA_FMT_STRING:
buflen = datalen + 1; buflen = datalen + 1;
break;
default:
buflen = datalen;
}
buf = kzalloc(buflen, GFP_KERNEL); buf = kzalloc(buflen, GFP_KERNEL);
if (!buf) if (!buf)
...@@ -63,7 +54,7 @@ static int ima_write_template_field_data(const void *data, const u32 datalen, ...@@ -63,7 +54,7 @@ static int ima_write_template_field_data(const void *data, const u32 datalen,
* split into multiple template fields (the space is the delimitator * split into multiple template fields (the space is the delimitator
* character for measurements lists in ASCII format). * character for measurements lists in ASCII format).
*/ */
if (datafmt == DATA_FMT_EVENT_NAME || datafmt == DATA_FMT_STRING) { if (datafmt == DATA_FMT_STRING) {
for (buf_ptr = buf; buf_ptr - buf < datalen; buf_ptr++) for (buf_ptr = buf; buf_ptr - buf < datalen; buf_ptr++)
if (*buf_ptr == ' ') if (*buf_ptr == ' ')
*buf_ptr = '_'; *buf_ptr = '_';
...@@ -109,13 +100,16 @@ static void ima_show_template_data_binary(struct seq_file *m, ...@@ -109,13 +100,16 @@ static void ima_show_template_data_binary(struct seq_file *m,
enum data_formats datafmt, enum data_formats datafmt,
struct ima_field_data *field_data) struct ima_field_data *field_data)
{ {
u32 len = (show == IMA_SHOW_BINARY_OLD_STRING_FMT) ?
strlen(field_data->data) : field_data->len;
if (show != IMA_SHOW_BINARY_NO_FIELD_LEN) if (show != IMA_SHOW_BINARY_NO_FIELD_LEN)
ima_putc(m, &field_data->len, sizeof(u32)); ima_putc(m, &len, sizeof(len));
if (!field_data->len) if (!len)
return; return;
ima_putc(m, field_data->data, field_data->len); ima_putc(m, field_data->data, len);
} }
static void ima_show_template_field_data(struct seq_file *m, static void ima_show_template_field_data(struct seq_file *m,
...@@ -129,6 +123,7 @@ static void ima_show_template_field_data(struct seq_file *m, ...@@ -129,6 +123,7 @@ static void ima_show_template_field_data(struct seq_file *m,
break; break;
case IMA_SHOW_BINARY: case IMA_SHOW_BINARY:
case IMA_SHOW_BINARY_NO_FIELD_LEN: case IMA_SHOW_BINARY_NO_FIELD_LEN:
case IMA_SHOW_BINARY_OLD_STRING_FMT:
ima_show_template_data_binary(m, show, datafmt, field_data); ima_show_template_data_binary(m, show, datafmt, field_data);
break; break;
default: default:
...@@ -277,8 +272,6 @@ static int ima_eventname_init_common(struct integrity_iint_cache *iint, ...@@ -277,8 +272,6 @@ static int ima_eventname_init_common(struct integrity_iint_cache *iint,
{ {
const char *cur_filename = NULL; const char *cur_filename = NULL;
u32 cur_filename_len = 0; u32 cur_filename_len = 0;
enum data_formats fmt = size_limit ?
DATA_FMT_EVENT_NAME : DATA_FMT_STRING;
BUG_ON(filename == NULL && file == NULL); BUG_ON(filename == NULL && file == NULL);
...@@ -301,7 +294,7 @@ static int ima_eventname_init_common(struct integrity_iint_cache *iint, ...@@ -301,7 +294,7 @@ static int ima_eventname_init_common(struct integrity_iint_cache *iint,
cur_filename_len = IMA_EVENT_NAME_LEN_MAX; cur_filename_len = IMA_EVENT_NAME_LEN_MAX;
out: out:
return ima_write_template_field_data(cur_filename, cur_filename_len, return ima_write_template_field_data(cur_filename, cur_filename_len,
fmt, field_data); DATA_FMT_STRING, field_data);
} }
/* /*
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* the Free Software Foundation, version 2 of the License. * the Free Software Foundation, version 2 of the License.
* *
* File: integrity_audit.c * File: integrity_audit.c
* Audit calls for the integrity subsystem * Audit calls for the integrity subsystem
*/ */
#include <linux/fs.h> #include <linux/fs.h>
...@@ -22,7 +22,7 @@ static int __init integrity_audit_setup(char *str) ...@@ -22,7 +22,7 @@ static int __init integrity_audit_setup(char *str)
{ {
unsigned long audit; unsigned long audit;
if (!strict_strtoul(str, 0, &audit)) if (!kstrtoul(str, 0, &audit))
integrity_audit_info = audit ? 1 : 0; integrity_audit_info = audit ? 1 : 0;
return 1; return 1;
} }
...@@ -33,6 +33,7 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode, ...@@ -33,6 +33,7 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
const char *cause, int result, int audit_info) const char *cause, int result, int audit_info)
{ {
struct audit_buffer *ab; struct audit_buffer *ab;
char name[TASK_COMM_LEN];
if (!integrity_audit_info && audit_info == 1) /* Skip info messages */ if (!integrity_audit_info && audit_info == 1) /* Skip info messages */
return; return;
...@@ -49,7 +50,7 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode, ...@@ -49,7 +50,7 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
audit_log_format(ab, " cause="); audit_log_format(ab, " cause=");
audit_log_string(ab, cause); audit_log_string(ab, cause);
audit_log_format(ab, " comm="); audit_log_format(ab, " comm=");
audit_log_untrustedstring(ab, current->comm); audit_log_untrustedstring(ab, get_task_comm(name, current));
if (fname) { if (fname) {
audit_log_format(ab, " name="); audit_log_format(ab, " name=");
audit_log_untrustedstring(ab, fname); audit_log_untrustedstring(ab, fname);
......
...@@ -609,7 +609,7 @@ static struct encrypted_key_payload *encrypted_key_alloc(struct key *key, ...@@ -609,7 +609,7 @@ static struct encrypted_key_payload *encrypted_key_alloc(struct key *key,
long dlen; long dlen;
int ret; int ret;
ret = strict_strtol(datalen, 10, &dlen); ret = kstrtol(datalen, 10, &dlen);
if (ret < 0 || dlen < MIN_DATA_SIZE || dlen > MAX_DATA_SIZE) if (ret < 0 || dlen < MIN_DATA_SIZE || dlen > MAX_DATA_SIZE)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
......
...@@ -753,7 +753,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay, ...@@ -753,7 +753,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
return -EINVAL; return -EINVAL;
break; break;
case Opt_keyhandle: case Opt_keyhandle:
res = strict_strtoul(args[0].from, 16, &handle); res = kstrtoul(args[0].from, 16, &handle);
if (res < 0) if (res < 0)
return -EINVAL; return -EINVAL;
opt->keytype = SEAL_keytype; opt->keytype = SEAL_keytype;
...@@ -782,7 +782,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay, ...@@ -782,7 +782,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
return -EINVAL; return -EINVAL;
break; break;
case Opt_pcrlock: case Opt_pcrlock:
res = strict_strtoul(args[0].from, 10, &lock); res = kstrtoul(args[0].from, 10, &lock);
if (res < 0) if (res < 0)
return -EINVAL; return -EINVAL;
opt->pcrlock = lock; opt->pcrlock = lock;
...@@ -820,7 +820,7 @@ static int datablob_parse(char *datablob, struct trusted_key_payload *p, ...@@ -820,7 +820,7 @@ static int datablob_parse(char *datablob, struct trusted_key_payload *p,
c = strsep(&datablob, " \t"); c = strsep(&datablob, " \t");
if (!c) if (!c)
return -EINVAL; return -EINVAL;
ret = strict_strtol(c, 10, &keylen); ret = kstrtol(c, 10, &keylen);
if (ret < 0 || keylen < MIN_KEY_SIZE || keylen > MAX_KEY_SIZE) if (ret < 0 || keylen < MIN_KEY_SIZE || keylen > MAX_KEY_SIZE)
return -EINVAL; return -EINVAL;
p->key_len = keylen; p->key_len = keylen;
......
...@@ -106,7 +106,7 @@ int selinux_enforcing; ...@@ -106,7 +106,7 @@ int selinux_enforcing;
static int __init enforcing_setup(char *str) static int __init enforcing_setup(char *str)
{ {
unsigned long enforcing; unsigned long enforcing;
if (!strict_strtoul(str, 0, &enforcing)) if (!kstrtoul(str, 0, &enforcing))
selinux_enforcing = enforcing ? 1 : 0; selinux_enforcing = enforcing ? 1 : 0;
return 1; return 1;
} }
...@@ -119,7 +119,7 @@ int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE; ...@@ -119,7 +119,7 @@ int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
static int __init selinux_enabled_setup(char *str) static int __init selinux_enabled_setup(char *str)
{ {
unsigned long enabled; unsigned long enabled;
if (!strict_strtoul(str, 0, &enabled)) if (!kstrtoul(str, 0, &enabled))
selinux_enabled = enabled ? 1 : 0; selinux_enabled = enabled ? 1 : 0;
return 1; return 1;
} }
...@@ -1418,15 +1418,33 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent ...@@ -1418,15 +1418,33 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
isec->sid = sbsec->sid; isec->sid = sbsec->sid;
if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) { if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) {
if (opt_dentry) { /* We must have a dentry to determine the label on
isec->sclass = inode_mode_to_security_class(inode->i_mode); * procfs inodes */
rc = selinux_proc_get_sid(opt_dentry, if (opt_dentry)
isec->sclass, /* Called from d_instantiate or
&sid); * d_splice_alias. */
if (rc) dentry = dget(opt_dentry);
goto out_unlock; else
isec->sid = sid; /* Called from selinux_complete_init, try to
} * find a dentry. */
dentry = d_find_alias(inode);
/*
* This can be hit on boot when a file is accessed
* before the policy is loaded. When we load policy we
* may find inodes that have no dentry on the
* sbsec->isec_head list. No reason to complain as
* these will get fixed up the next time we go through
* inode_doinit() with a dentry, before these inodes
* could be used again by userspace.
*/
if (!dentry)
goto out_unlock;
isec->sclass = inode_mode_to_security_class(inode->i_mode);
rc = selinux_proc_get_sid(dentry, isec->sclass, &sid);
dput(dentry);
if (rc)
goto out_unlock;
isec->sid = sid;
} }
break; break;
} }
...@@ -3205,24 +3223,20 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared ...@@ -3205,24 +3223,20 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared
static int selinux_mmap_addr(unsigned long addr) static int selinux_mmap_addr(unsigned long addr)
{ {
int rc = 0; int rc;
u32 sid = current_sid();
/* do DAC check on address space usage */
rc = cap_mmap_addr(addr);
if (rc)
return rc;
/*
* notice that we are intentionally putting the SELinux check before
* the secondary cap_file_mmap check. This is such a likely attempt
* at bad behaviour/exploit that we always want to get the AVC, even
* if DAC would have also denied the operation.
*/
if (addr < CONFIG_LSM_MMAP_MIN_ADDR) { if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
u32 sid = current_sid();
rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT, rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
MEMPROTECT__MMAP_ZERO, NULL); MEMPROTECT__MMAP_ZERO, NULL);
if (rc)
return rc;
} }
/* do DAC check on address space usage */ return rc;
return cap_mmap_addr(addr);
} }
static int selinux_mmap_file(struct file *file, unsigned long reqprot, static int selinux_mmap_file(struct file *file, unsigned long reqprot,
......
...@@ -54,7 +54,7 @@ unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; ...@@ -54,7 +54,7 @@ unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
static int __init checkreqprot_setup(char *str) static int __init checkreqprot_setup(char *str)
{ {
unsigned long checkreqprot; unsigned long checkreqprot;
if (!strict_strtoul(str, 0, &checkreqprot)) if (!kstrtoul(str, 0, &checkreqprot))
selinux_checkreqprot = checkreqprot ? 1 : 0; selinux_checkreqprot = checkreqprot ? 1 : 0;
return 1; return 1;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment