Commit e22619a2 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull security subsystem updates from James Morris:
 "The main change in this kernel is Casey's generalized LSM stacking
  work, which removes the hard-coding of Capabilities and Yama stacking,
  allowing multiple arbitrary "small" LSMs to be stacked with a default
  monolithic module (e.g.  SELinux, Smack, AppArmor).

  See
        https://lwn.net/Articles/636056/

  This will allow smaller, simpler LSMs to be incorporated into the
  mainline kernel and arbitrarily stacked by users.  Also, this is a
  useful cleanup of the LSM code in its own right"

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (38 commits)
  tpm, tpm_crb: fix le64_to_cpu conversions in crb_acpi_add()
  vTPM: set virtual device before passing to ibmvtpm_reset_crq
  tpm_ibmvtpm: remove unneccessary message level.
  ima: update builtin policies
  ima: extend "mask" policy matching support
  ima: add support for new "euid" policy condition
  ima: fix ima_show_template_data_ascii()
  Smack: freeing an error pointer in smk_write_revoke_subj()
  selinux: fix setting of security labels on NFS
  selinux: Remove unused permission definitions
  selinux: enable genfscon labeling for sysfs and pstore files
  selinux: enable per-file labeling for debugfs files.
  selinux: update netlink socket classes
  signals: don't abuse __flush_signals() in selinux_bprm_committed_creds()
  selinux: Print 'sclass' as string when unrecognized netlink message occurs
  Smack: allow multiple labels in onlycap
  Smack: fix seq operations in smackfs
  ima: pass iint to ima_add_violation()
  ima: wrap event related data to the new ima_event_data structure
  integrity: add validity checks for 'path' parameter
  ...
parents 78c10e55 b3bddffd
...@@ -20,17 +20,19 @@ Description: ...@@ -20,17 +20,19 @@ Description:
action: measure | dont_measure | appraise | dont_appraise | audit action: measure | dont_measure | appraise | dont_appraise | audit
condition:= base | lsm [option] condition:= base | lsm [option]
base: [[func=] [mask=] [fsmagic=] [fsuuid=] [uid=] base: [[func=] [mask=] [fsmagic=] [fsuuid=] [uid=]
[fowner]] [euid=] [fowner=]]
lsm: [[subj_user=] [subj_role=] [subj_type=] lsm: [[subj_user=] [subj_role=] [subj_type=]
[obj_user=] [obj_role=] [obj_type=]] [obj_user=] [obj_role=] [obj_type=]]
option: [[appraise_type=]] [permit_directio] option: [[appraise_type=]] [permit_directio]
base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK] base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
[FIRMWARE_CHECK] [FIRMWARE_CHECK]
mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC] mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
[[^]MAY_EXEC]
fsmagic:= hex value fsmagic:= hex value
fsuuid:= file system UUID (e.g 8bcbe394-4f13-4144-be8e-5aa9ea2ce2f6) fsuuid:= file system UUID (e.g 8bcbe394-4f13-4144-be8e-5aa9ea2ce2f6)
uid:= decimal value uid:= decimal value
euid:= decimal value
fowner:=decimal value fowner:=decimal value
lsm: are LSM specific lsm: are LSM specific
option: appraise_type:= [imasig] option: appraise_type:= [imasig]
...@@ -49,11 +51,25 @@ Description: ...@@ -49,11 +51,25 @@ Description:
dont_measure fsmagic=0x01021994 dont_measure fsmagic=0x01021994
dont_appraise fsmagic=0x01021994 dont_appraise fsmagic=0x01021994
# RAMFS_MAGIC # RAMFS_MAGIC
dont_measure fsmagic=0x858458f6
dont_appraise fsmagic=0x858458f6 dont_appraise fsmagic=0x858458f6
# DEVPTS_SUPER_MAGIC
dont_measure fsmagic=0x1cd1
dont_appraise fsmagic=0x1cd1
# BINFMTFS_MAGIC
dont_measure fsmagic=0x42494e4d
dont_appraise fsmagic=0x42494e4d
# SECURITYFS_MAGIC # SECURITYFS_MAGIC
dont_measure fsmagic=0x73636673 dont_measure fsmagic=0x73636673
dont_appraise fsmagic=0x73636673 dont_appraise fsmagic=0x73636673
# SELINUX_MAGIC
dont_measure fsmagic=0xf97cff8c
dont_appraise fsmagic=0xf97cff8c
# CGROUP_SUPER_MAGIC
dont_measure fsmagic=0x27e0eb
dont_appraise fsmagic=0x27e0eb
# NSFS_MAGIC
dont_measure fsmagic=0x6e736673
dont_appraise fsmagic=0x6e736673
measure func=BPRM_CHECK measure func=BPRM_CHECK
measure func=FILE_MMAP mask=MAY_EXEC measure func=FILE_MMAP mask=MAY_EXEC
...@@ -70,10 +86,6 @@ Description: ...@@ -70,10 +86,6 @@ Description:
Examples of LSM specific definitions: Examples of LSM specific definitions:
SELinux: SELinux:
# SELINUX_MAGIC
dont_measure fsmagic=0xf97cff8c
dont_appraise fsmagic=0xf97cff8c
dont_measure obj_type=var_log_t dont_measure obj_type=var_log_t
dont_appraise obj_type=var_log_t dont_appraise obj_type=var_log_t
dont_measure obj_type=auditd_log_t dont_measure obj_type=auditd_log_t
......
...@@ -1413,7 +1413,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted. ...@@ -1413,7 +1413,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
The list of supported hash algorithms is defined The list of supported hash algorithms is defined
in crypto/hash_info.h. in crypto/hash_info.h.
ima_tcb [IMA] ima_policy= [IMA]
The builtin measurement policy to load during IMA
setup. Specyfing "tcb" as the value, measures all
programs exec'd, files mmap'd for exec, and all files
opened with the read mode bit set by either the
effective uid (euid=0) or uid=0.
Format: "tcb"
ima_tcb [IMA] Deprecated. Use ima_policy= instead.
Load a policy which meets the needs of the Trusted Load a policy which meets the needs of the Trusted
Computing Base. This means IMA will measure all Computing Base. This means IMA will measure all
programs exec'd, files mmap'd for exec, and all files programs exec'd, files mmap'd for exec, and all files
...@@ -1421,7 +1429,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. ...@@ -1421,7 +1429,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
ima_template= [IMA] ima_template= [IMA]
Select one of defined IMA measurements template formats. Select one of defined IMA measurements template formats.
Formats: { "ima" | "ima-ng" } Formats: { "ima" | "ima-ng" | "ima-sig" }
Default: "ima-ng" Default: "ima-ng"
ima_template_fmt= ima_template_fmt=
......
...@@ -206,11 +206,11 @@ netlabel ...@@ -206,11 +206,11 @@ netlabel
label. The format accepted on write is: label. The format accepted on write is:
"%d.%d.%d.%d label" or "%d.%d.%d.%d/%d label". "%d.%d.%d.%d label" or "%d.%d.%d.%d/%d label".
onlycap onlycap
This contains the label processes must have for CAP_MAC_ADMIN This contains labels processes must have for CAP_MAC_ADMIN
and CAP_MAC_OVERRIDE to be effective. If this file is empty and CAP_MAC_OVERRIDE to be effective. If this file is empty
these capabilities are effective at for processes with any these capabilities are effective at for processes with any
label. The value is set by writing the desired label to the label. The values are set by writing the desired labels, separated
file or cleared by writing "-" to the file. by spaces, to the file or cleared by writing "-" to the file.
ptrace ptrace
This is used to define the current ptrace policy This is used to define the current ptrace policy
0 - default: this is the policy that relies on Smack access rules. 0 - default: this is the policy that relies on Smack access rules.
......
...@@ -11,6 +11,9 @@ ...@@ -11,6 +11,9 @@
extern struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id); extern struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id);
extern int __asymmetric_key_hex_to_key_id(const char *id,
struct asymmetric_key_id *match_id,
size_t hexlen);
static inline static inline
const struct asymmetric_key_ids *asymmetric_key_ids(const struct key *key) const struct asymmetric_key_ids *asymmetric_key_ids(const struct key *key)
{ {
......
...@@ -104,6 +104,15 @@ static bool asymmetric_match_key_ids( ...@@ -104,6 +104,15 @@ static bool asymmetric_match_key_ids(
return false; return false;
} }
/* helper function can be called directly with pre-allocated memory */
inline int __asymmetric_key_hex_to_key_id(const char *id,
struct asymmetric_key_id *match_id,
size_t hexlen)
{
match_id->len = hexlen;
return hex2bin(match_id->data, id, hexlen);
}
/** /**
* asymmetric_key_hex_to_key_id - Convert a hex string into a key ID. * asymmetric_key_hex_to_key_id - Convert a hex string into a key ID.
* @id: The ID as a hex string. * @id: The ID as a hex string.
...@@ -111,21 +120,20 @@ static bool asymmetric_match_key_ids( ...@@ -111,21 +120,20 @@ static bool asymmetric_match_key_ids(
struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id) struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id)
{ {
struct asymmetric_key_id *match_id; struct asymmetric_key_id *match_id;
size_t hexlen; size_t asciihexlen;
int ret; int ret;
if (!*id) if (!*id)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
hexlen = strlen(id); asciihexlen = strlen(id);
if (hexlen & 1) if (asciihexlen & 1)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
match_id = kmalloc(sizeof(struct asymmetric_key_id) + hexlen / 2, match_id = kmalloc(sizeof(struct asymmetric_key_id) + asciihexlen / 2,
GFP_KERNEL); GFP_KERNEL);
if (!match_id) if (!match_id)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
match_id->len = hexlen / 2; ret = __asymmetric_key_hex_to_key_id(id, match_id, asciihexlen / 2);
ret = hex2bin(match_id->data, id, hexlen / 2);
if (ret < 0) { if (ret < 0) {
kfree(match_id); kfree(match_id);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
......
...@@ -28,17 +28,30 @@ static bool use_builtin_keys; ...@@ -28,17 +28,30 @@ static bool use_builtin_keys;
static struct asymmetric_key_id *ca_keyid; static struct asymmetric_key_id *ca_keyid;
#ifndef MODULE #ifndef MODULE
static struct {
struct asymmetric_key_id id;
unsigned char data[10];
} cakey;
static int __init ca_keys_setup(char *str) static int __init ca_keys_setup(char *str)
{ {
if (!str) /* default system keyring */ if (!str) /* default system keyring */
return 1; return 1;
if (strncmp(str, "id:", 3) == 0) { if (strncmp(str, "id:", 3) == 0) {
struct asymmetric_key_id *p; struct asymmetric_key_id *p = &cakey.id;
p = asymmetric_key_hex_to_key_id(str + 3); size_t hexlen = (strlen(str) - 3) / 2;
if (p == ERR_PTR(-EINVAL)) int ret;
pr_err("Unparsable hex string in ca_keys\n");
else if (!IS_ERR(p)) if (hexlen == 0 || hexlen > sizeof(cakey.data)) {
pr_err("Missing or invalid ca_keys id\n");
return 1;
}
ret = __asymmetric_key_hex_to_key_id(str + 3, p, hexlen);
if (ret < 0)
pr_err("Unparsable ca_keys id hex string\n");
else
ca_keyid = p; /* owner key 'id:xxxxxx' */ ca_keyid = p; /* owner key 'id:xxxxxx' */
} else if (strcmp(str, "builtin") == 0) { } else if (strcmp(str, "builtin") == 0) {
use_builtin_keys = true; use_builtin_keys = true;
......
...@@ -267,7 +267,7 @@ static int crb_acpi_add(struct acpi_device *device) ...@@ -267,7 +267,7 @@ static int crb_acpi_add(struct acpi_device *device)
memcpy_fromio(&pa, &priv->cca->cmd_pa, 8); memcpy_fromio(&pa, &priv->cca->cmd_pa, 8);
pa = le64_to_cpu(pa); pa = le64_to_cpu(pa);
priv->cmd = devm_ioremap_nocache(dev, le64_to_cpu(pa), priv->cmd = devm_ioremap_nocache(dev, pa,
ioread32(&priv->cca->cmd_size)); ioread32(&priv->cca->cmd_size));
if (!priv->cmd) { if (!priv->cmd) {
dev_err(dev, "ioremap of the command buffer failed\n"); dev_err(dev, "ioremap of the command buffer failed\n");
...@@ -276,7 +276,7 @@ static int crb_acpi_add(struct acpi_device *device) ...@@ -276,7 +276,7 @@ static int crb_acpi_add(struct acpi_device *device)
memcpy_fromio(&pa, &priv->cca->rsp_pa, 8); memcpy_fromio(&pa, &priv->cca->rsp_pa, 8);
pa = le64_to_cpu(pa); pa = le64_to_cpu(pa);
priv->rsp = devm_ioremap_nocache(dev, le64_to_cpu(pa), priv->rsp = devm_ioremap_nocache(dev, pa,
ioread32(&priv->cca->rsp_size)); ioread32(&priv->cca->rsp_size));
if (!priv->rsp) { if (!priv->rsp) {
dev_err(dev, "ioremap of the response buffer failed\n"); dev_err(dev, "ioremap of the response buffer failed\n");
......
...@@ -578,6 +578,9 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, ...@@ -578,6 +578,9 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
goto cleanup; goto cleanup;
} }
ibmvtpm->dev = dev;
ibmvtpm->vdev = vio_dev;
crq_q = &ibmvtpm->crq_queue; crq_q = &ibmvtpm->crq_queue;
crq_q->crq_addr = (struct ibmvtpm_crq *)get_zeroed_page(GFP_KERNEL); crq_q->crq_addr = (struct ibmvtpm_crq *)get_zeroed_page(GFP_KERNEL);
if (!crq_q->crq_addr) { if (!crq_q->crq_addr) {
...@@ -622,8 +625,6 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, ...@@ -622,8 +625,6 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
crq_q->index = 0; crq_q->index = 0;
ibmvtpm->dev = dev;
ibmvtpm->vdev = vio_dev;
TPM_VPRIV(chip) = (void *)ibmvtpm; TPM_VPRIV(chip) = (void *)ibmvtpm;
spin_lock_init(&ibmvtpm->rtce_lock); spin_lock_init(&ibmvtpm->rtce_lock);
......
...@@ -49,7 +49,7 @@ int read_log(struct tpm_bios_log *log) ...@@ -49,7 +49,7 @@ int read_log(struct tpm_bios_log *log)
basep = of_get_property(np, "linux,sml-base", NULL); basep = of_get_property(np, "linux,sml-base", NULL);
if (basep == NULL) { if (basep == NULL) {
pr_err(KERN_ERR "%s: ERROR - SML not found\n", __func__); pr_err("%s: ERROR - SML not found\n", __func__);
goto cleanup_eio; goto cleanup_eio;
} }
......
...@@ -298,18 +298,18 @@ vfs_removexattr(struct dentry *dentry, const char *name) ...@@ -298,18 +298,18 @@ vfs_removexattr(struct dentry *dentry, const char *name)
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
error = security_inode_removexattr(dentry, name); error = security_inode_removexattr(dentry, name);
if (error) { if (error)
mutex_unlock(&inode->i_mutex); goto out;
return error;
}
error = inode->i_op->removexattr(dentry, name); error = inode->i_op->removexattr(dentry, name);
mutex_unlock(&inode->i_mutex);
if (!error) { if (!error) {
fsnotify_xattr(dentry); fsnotify_xattr(dentry);
evm_inode_post_removexattr(dentry, name); evm_inode_post_removexattr(dentry, name);
} }
out:
mutex_unlock(&inode->i_mutex);
return error; return error;
} }
EXPORT_SYMBOL_GPL(vfs_removexattr); EXPORT_SYMBOL_GPL(vfs_removexattr);
......
This diff is collapsed.
...@@ -2421,7 +2421,6 @@ extern void sched_dead(struct task_struct *p); ...@@ -2421,7 +2421,6 @@ extern void sched_dead(struct task_struct *p);
extern void proc_caches_init(void); extern void proc_caches_init(void);
extern void flush_signals(struct task_struct *); extern void flush_signals(struct task_struct *);
extern void __flush_signals(struct task_struct *);
extern void ignore_signals(struct task_struct *); extern void ignore_signals(struct task_struct *);
extern void flush_signal_handlers(struct task_struct *, int force_default); extern void flush_signal_handlers(struct task_struct *, int force_default);
extern int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info); extern int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info);
......
This diff is collapsed.
...@@ -414,21 +414,16 @@ void flush_sigqueue(struct sigpending *queue) ...@@ -414,21 +414,16 @@ void flush_sigqueue(struct sigpending *queue)
} }
/* /*
* Flush all pending signals for a task. * Flush all pending signals for this kthread.
*/ */
void __flush_signals(struct task_struct *t)
{
clear_tsk_thread_flag(t, TIF_SIGPENDING);
flush_sigqueue(&t->pending);
flush_sigqueue(&t->signal->shared_pending);
}
void flush_signals(struct task_struct *t) void flush_signals(struct task_struct *t)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&t->sighand->siglock, flags); spin_lock_irqsave(&t->sighand->siglock, flags);
__flush_signals(t); clear_tsk_thread_flag(t, TIF_SIGPENDING);
flush_sigqueue(&t->pending);
flush_sigqueue(&t->signal->shared_pending);
spin_unlock_irqrestore(&t->sighand->siglock, flags); spin_unlock_irqrestore(&t->sighand->siglock, flags);
} }
......
...@@ -14,7 +14,7 @@ obj-y += commoncap.o ...@@ -14,7 +14,7 @@ obj-y += commoncap.o
obj-$(CONFIG_MMU) += min_addr.o obj-$(CONFIG_MMU) += min_addr.o
# Object file lists # Object file lists
obj-$(CONFIG_SECURITY) += security.o capability.o obj-$(CONFIG_SECURITY) += security.o
obj-$(CONFIG_SECURITYFS) += inode.o obj-$(CONFIG_SECURITYFS) += inode.o
obj-$(CONFIG_SECURITY_SELINUX) += selinux/ obj-$(CONFIG_SECURITY_SELINUX) += selinux/
obj-$(CONFIG_SECURITY_SMACK) += smack/ obj-$(CONFIG_SECURITY_SMACK) += smack/
......
...@@ -347,9 +347,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) ...@@ -347,9 +347,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
file_inode(bprm->file)->i_mode file_inode(bprm->file)->i_mode
}; };
const char *name = NULL, *target = NULL, *info = NULL; const char *name = NULL, *target = NULL, *info = NULL;
int error = cap_bprm_set_creds(bprm); int error = 0;
if (error)
return error;
if (bprm->cred_prepared) if (bprm->cred_prepared)
return 0; return 0;
...@@ -531,15 +529,13 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) ...@@ -531,15 +529,13 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
*/ */
int apparmor_bprm_secureexec(struct linux_binprm *bprm) int apparmor_bprm_secureexec(struct linux_binprm *bprm)
{ {
int ret = cap_bprm_secureexec(bprm);
/* the decision to use secure exec is computed in set_creds /* the decision to use secure exec is computed in set_creds
* and stored in bprm->unsafe. * and stored in bprm->unsafe.
*/ */
if (!ret && (bprm->unsafe & AA_SECURE_X_NEEDED)) if (bprm->unsafe & AA_SECURE_X_NEEDED)
ret = 1; return 1;
return ret; return 0;
} }
/** /**
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* License. * License.
*/ */
#include <linux/security.h> #include <linux/lsm_hooks.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/mman.h> #include <linux/mman.h>
...@@ -96,19 +96,11 @@ static void apparmor_cred_transfer(struct cred *new, const struct cred *old) ...@@ -96,19 +96,11 @@ static void apparmor_cred_transfer(struct cred *new, const struct cred *old)
static int apparmor_ptrace_access_check(struct task_struct *child, static int apparmor_ptrace_access_check(struct task_struct *child,
unsigned int mode) unsigned int mode)
{ {
int error = cap_ptrace_access_check(child, mode);
if (error)
return error;
return aa_ptrace(current, child, mode); return aa_ptrace(current, child, mode);
} }
static int apparmor_ptrace_traceme(struct task_struct *parent) static int apparmor_ptrace_traceme(struct task_struct *parent)
{ {
int error = cap_ptrace_traceme(parent);
if (error)
return error;
return aa_ptrace(parent, current, PTRACE_MODE_ATTACH); return aa_ptrace(parent, current, PTRACE_MODE_ATTACH);
} }
...@@ -123,10 +115,10 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective, ...@@ -123,10 +115,10 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
cred = __task_cred(target); cred = __task_cred(target);
profile = aa_cred_profile(cred); profile = aa_cred_profile(cred);
*effective = cred->cap_effective; /*
*inheritable = cred->cap_inheritable; * cap_capget is stacked ahead of this and will
*permitted = cred->cap_permitted; * initialize effective and permitted.
*/
if (!unconfined(profile) && !COMPLAIN_MODE(profile)) { if (!unconfined(profile) && !COMPLAIN_MODE(profile)) {
*effective = cap_intersect(*effective, profile->caps.allow); *effective = cap_intersect(*effective, profile->caps.allow);
*permitted = cap_intersect(*permitted, profile->caps.allow); *permitted = cap_intersect(*permitted, profile->caps.allow);
...@@ -140,13 +132,11 @@ static int apparmor_capable(const struct cred *cred, struct user_namespace *ns, ...@@ -140,13 +132,11 @@ static int apparmor_capable(const struct cred *cred, struct user_namespace *ns,
int cap, int audit) int cap, int audit)
{ {
struct aa_profile *profile; struct aa_profile *profile;
/* cap_capable returns 0 on success, else -EPERM */ int error = 0;
int error = cap_capable(cred, ns, cap, audit);
if (!error) {
profile = aa_cred_profile(cred); profile = aa_cred_profile(cred);
if (!unconfined(profile)) if (!unconfined(profile))
error = aa_capable(profile, cap, audit); error = aa_capable(profile, cap, audit);
}
return error; return error;
} }
...@@ -615,49 +605,46 @@ static int apparmor_task_setrlimit(struct task_struct *task, ...@@ -615,49 +605,46 @@ static int apparmor_task_setrlimit(struct task_struct *task,
return error; return error;
} }
static struct security_operations apparmor_ops = { static struct security_hook_list apparmor_hooks[] = {
.name = "apparmor", LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
.ptrace_access_check = apparmor_ptrace_access_check, LSM_HOOK_INIT(capget, apparmor_capget),
.ptrace_traceme = apparmor_ptrace_traceme, LSM_HOOK_INIT(capable, apparmor_capable),
.capget = apparmor_capget,
.capable = apparmor_capable, LSM_HOOK_INIT(path_link, apparmor_path_link),
LSM_HOOK_INIT(path_unlink, apparmor_path_unlink),
.path_link = apparmor_path_link, LSM_HOOK_INIT(path_symlink, apparmor_path_symlink),
.path_unlink = apparmor_path_unlink, LSM_HOOK_INIT(path_mkdir, apparmor_path_mkdir),
.path_symlink = apparmor_path_symlink, LSM_HOOK_INIT(path_rmdir, apparmor_path_rmdir),
.path_mkdir = apparmor_path_mkdir, LSM_HOOK_INIT(path_mknod, apparmor_path_mknod),
.path_rmdir = apparmor_path_rmdir, LSM_HOOK_INIT(path_rename, apparmor_path_rename),
.path_mknod = apparmor_path_mknod, LSM_HOOK_INIT(path_chmod, apparmor_path_chmod),
.path_rename = apparmor_path_rename, LSM_HOOK_INIT(path_chown, apparmor_path_chown),
.path_chmod = apparmor_path_chmod, LSM_HOOK_INIT(path_truncate, apparmor_path_truncate),
.path_chown = apparmor_path_chown, LSM_HOOK_INIT(inode_getattr, apparmor_inode_getattr),
.path_truncate = apparmor_path_truncate,
.inode_getattr = apparmor_inode_getattr, LSM_HOOK_INIT(file_open, apparmor_file_open),
LSM_HOOK_INIT(file_permission, apparmor_file_permission),
.file_open = apparmor_file_open, LSM_HOOK_INIT(file_alloc_security, apparmor_file_alloc_security),
.file_permission = apparmor_file_permission, LSM_HOOK_INIT(file_free_security, apparmor_file_free_security),
.file_alloc_security = apparmor_file_alloc_security, LSM_HOOK_INIT(mmap_file, apparmor_mmap_file),
.file_free_security = apparmor_file_free_security, LSM_HOOK_INIT(file_mprotect, apparmor_file_mprotect),
.mmap_file = apparmor_mmap_file, LSM_HOOK_INIT(file_lock, apparmor_file_lock),
.mmap_addr = cap_mmap_addr,
.file_mprotect = apparmor_file_mprotect, LSM_HOOK_INIT(getprocattr, apparmor_getprocattr),
.file_lock = apparmor_file_lock, LSM_HOOK_INIT(setprocattr, apparmor_setprocattr),
.getprocattr = apparmor_getprocattr, LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank),
.setprocattr = apparmor_setprocattr, LSM_HOOK_INIT(cred_free, apparmor_cred_free),
LSM_HOOK_INIT(cred_prepare, apparmor_cred_prepare),
.cred_alloc_blank = apparmor_cred_alloc_blank, LSM_HOOK_INIT(cred_transfer, apparmor_cred_transfer),
.cred_free = apparmor_cred_free,
.cred_prepare = apparmor_cred_prepare, LSM_HOOK_INIT(bprm_set_creds, apparmor_bprm_set_creds),
.cred_transfer = apparmor_cred_transfer, LSM_HOOK_INIT(bprm_committing_creds, apparmor_bprm_committing_creds),
LSM_HOOK_INIT(bprm_committed_creds, apparmor_bprm_committed_creds),
.bprm_set_creds = apparmor_bprm_set_creds, LSM_HOOK_INIT(bprm_secureexec, apparmor_bprm_secureexec),
.bprm_committing_creds = apparmor_bprm_committing_creds,
.bprm_committed_creds = apparmor_bprm_committed_creds, LSM_HOOK_INIT(task_setrlimit, apparmor_task_setrlimit),
.bprm_secureexec = apparmor_bprm_secureexec,
.task_setrlimit = apparmor_task_setrlimit,
}; };
/* /*
...@@ -898,7 +885,7 @@ static int __init apparmor_init(void) ...@@ -898,7 +885,7 @@ static int __init apparmor_init(void)
{ {
int error; int error;
if (!apparmor_enabled || !security_module_enable(&apparmor_ops)) { if (!apparmor_enabled || !security_module_enable("apparmor")) {
aa_info_message("AppArmor disabled by boot time parameter"); aa_info_message("AppArmor disabled by boot time parameter");
apparmor_enabled = 0; apparmor_enabled = 0;
return 0; return 0;
...@@ -913,17 +900,10 @@ static int __init apparmor_init(void) ...@@ -913,17 +900,10 @@ static int __init apparmor_init(void)
error = set_init_cxt(); error = set_init_cxt();
if (error) { if (error) {
AA_ERROR("Failed to set context on init task\n"); AA_ERROR("Failed to set context on init task\n");
goto register_security_out; aa_free_root_ns();
} goto alloc_out;
error = register_security(&apparmor_ops);
if (error) {
struct cred *cred = (struct cred *)current->real_cred;
aa_free_task_context(cred_cxt(cred));
cred_cxt(cred) = NULL;
AA_ERROR("Unable to register AppArmor\n");
goto register_security_out;
} }
security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks));
/* Report that AppArmor successfully initialized */ /* Report that AppArmor successfully initialized */
apparmor_initialized = 1; apparmor_initialized = 1;
...@@ -936,9 +916,6 @@ static int __init apparmor_init(void) ...@@ -936,9 +916,6 @@ static int __init apparmor_init(void)
return error; return error;
register_security_out:
aa_free_root_ns();
alloc_out: alloc_out:
aa_destroy_aafs(); aa_destroy_aafs();
......
This diff is collapsed.
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/security.h> #include <linux/lsm_hooks.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/mman.h> #include <linux/mman.h>
...@@ -53,11 +53,6 @@ static void warn_setuid_and_fcaps_mixed(const char *fname) ...@@ -53,11 +53,6 @@ static void warn_setuid_and_fcaps_mixed(const char *fname)
} }
} }
int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
{
return 0;
}
/** /**
* cap_capable - Determine whether a task has a particular effective capability * cap_capable - Determine whether a task has a particular effective capability
* @cred: The credentials to use * @cred: The credentials to use
...@@ -941,7 +936,7 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, ...@@ -941,7 +936,7 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
* @pages: The size of the mapping * @pages: The size of the mapping
* *
* Determine whether the allocation of a new virtual mapping by the current * Determine whether the allocation of a new virtual mapping by the current
* task is permitted, returning 0 if permission is granted, -ve if not. * task is permitted, returning 1 if permission is granted, 0 if not.
*/ */
int cap_vm_enough_memory(struct mm_struct *mm, long pages) int cap_vm_enough_memory(struct mm_struct *mm, long pages)
{ {
...@@ -950,7 +945,7 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages) ...@@ -950,7 +945,7 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages)
if (cap_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN, if (cap_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
SECURITY_CAP_NOAUDIT) == 0) SECURITY_CAP_NOAUDIT) == 0)
cap_sys_admin = 1; cap_sys_admin = 1;
return __vm_enough_memory(mm, pages, cap_sys_admin); return cap_sys_admin;
} }
/* /*
...@@ -981,3 +976,33 @@ int cap_mmap_file(struct file *file, unsigned long reqprot, ...@@ -981,3 +976,33 @@ int cap_mmap_file(struct file *file, unsigned long reqprot,
{ {
return 0; return 0;
} }
#ifdef CONFIG_SECURITY
struct security_hook_list capability_hooks[] = {
LSM_HOOK_INIT(capable, cap_capable),
LSM_HOOK_INIT(settime, cap_settime),
LSM_HOOK_INIT(ptrace_access_check, cap_ptrace_access_check),
LSM_HOOK_INIT(ptrace_traceme, cap_ptrace_traceme),
LSM_HOOK_INIT(capget, cap_capget),
LSM_HOOK_INIT(capset, cap_capset),
LSM_HOOK_INIT(bprm_set_creds, cap_bprm_set_creds),
LSM_HOOK_INIT(bprm_secureexec, cap_bprm_secureexec),
LSM_HOOK_INIT(inode_need_killpriv, cap_inode_need_killpriv),
LSM_HOOK_INIT(inode_killpriv, cap_inode_killpriv),
LSM_HOOK_INIT(mmap_addr, cap_mmap_addr),
LSM_HOOK_INIT(mmap_file, cap_mmap_file),
LSM_HOOK_INIT(task_fix_setuid, cap_task_fix_setuid),
LSM_HOOK_INIT(task_prctl, cap_task_prctl),
LSM_HOOK_INIT(task_setscheduler, cap_task_setscheduler),
LSM_HOOK_INIT(task_setioprio, cap_task_setioprio),
LSM_HOOK_INIT(task_setnice, cap_task_setnice),
LSM_HOOK_INIT(vm_enough_memory, cap_vm_enough_memory),
};
void __init capability_add_hooks(void)
{
security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks));
}
#endif /* CONFIG_SECURITY */
...@@ -85,7 +85,7 @@ int __init integrity_init_keyring(const unsigned int id) ...@@ -85,7 +85,7 @@ int __init integrity_init_keyring(const unsigned int id)
return err; return err;
} }
int __init integrity_load_x509(const unsigned int id, char *path) int __init integrity_load_x509(const unsigned int id, const char *path)
{ {
key_ref_t key; key_ref_t key;
char *data; char *data;
......
...@@ -296,6 +296,17 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name, ...@@ -296,6 +296,17 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name,
iint = integrity_iint_find(d_backing_inode(dentry)); iint = integrity_iint_find(d_backing_inode(dentry));
if (iint && (iint->flags & IMA_NEW_FILE)) if (iint && (iint->flags & IMA_NEW_FILE))
return 0; return 0;
/* exception for pseudo filesystems */
if (dentry->d_inode->i_sb->s_magic == TMPFS_MAGIC
|| dentry->d_inode->i_sb->s_magic == SYSFS_MAGIC)
return 0;
integrity_audit_msg(AUDIT_INTEGRITY_METADATA,
dentry->d_inode, dentry->d_name.name,
"update_metadata",
integrity_status_msg[evm_status],
-EPERM, 0);
} }
out: out:
if (evm_status != INTEGRITY_PASS) if (evm_status != INTEGRITY_PASS)
...@@ -376,17 +387,16 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, ...@@ -376,17 +387,16 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
* @xattr_name: pointer to the affected extended attribute name * @xattr_name: pointer to the affected extended attribute name
* *
* Update the HMAC stored in 'security.evm' to reflect removal of the xattr. * Update the HMAC stored in 'security.evm' to reflect removal of the xattr.
*
* No need to take the i_mutex lock here, as this function is called from
* vfs_removexattr() which takes the i_mutex.
*/ */
void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name) void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
{ {
struct inode *inode = d_backing_inode(dentry);
if (!evm_initialized || !evm_protected_xattr(xattr_name)) if (!evm_initialized || !evm_protected_xattr(xattr_name))
return; return;
mutex_lock(&inode->i_mutex);
evm_update_evmxattr(dentry, xattr_name, NULL, 0); evm_update_evmxattr(dentry, xattr_name, NULL, 0);
mutex_unlock(&inode->i_mutex);
} }
/** /**
......
...@@ -213,6 +213,9 @@ int __init integrity_read_file(const char *path, char **data) ...@@ -213,6 +213,9 @@ int __init integrity_read_file(const char *path, char **data)
char *buf; char *buf;
int rc = -EINVAL; int rc = -EINVAL;
if (!path || !*path)
return -EINVAL;
file = filp_open(path, O_RDONLY, 0); file = filp_open(path, O_RDONLY, 0);
if (IS_ERR(file)) { if (IS_ERR(file)) {
rc = PTR_ERR(file); rc = PTR_ERR(file);
......
...@@ -52,6 +52,16 @@ extern int ima_used_chip; ...@@ -52,6 +52,16 @@ extern int ima_used_chip;
extern int ima_hash_algo; extern int ima_hash_algo;
extern int ima_appraise; extern int ima_appraise;
/* IMA event related data */
struct ima_event_data {
struct integrity_iint_cache *iint;
struct file *file;
const unsigned char *filename;
struct evm_ima_xattr_data *xattr_value;
int xattr_len;
const char *violation;
};
/* IMA template field data definition */ /* IMA template field data definition */
struct ima_field_data { struct ima_field_data {
u8 *data; u8 *data;
...@@ -61,11 +71,9 @@ struct ima_field_data { ...@@ -61,11 +71,9 @@ struct ima_field_data {
/* IMA template field definition */ /* IMA template field definition */
struct ima_template_field { struct ima_template_field {
const char field_id[IMA_TEMPLATE_FIELD_ID_MAX_LEN]; const char field_id[IMA_TEMPLATE_FIELD_ID_MAX_LEN];
int (*field_init) (struct integrity_iint_cache *iint, struct file *file, int (*field_init)(struct ima_event_data *event_data,
const unsigned char *filename, struct ima_field_data *field_data);
struct evm_ima_xattr_data *xattr_value, void (*field_show)(struct seq_file *m, enum ima_show_type show,
int xattr_len, struct ima_field_data *field_data);
void (*field_show) (struct seq_file *m, enum ima_show_type show,
struct ima_field_data *field_data); struct ima_field_data *field_data);
}; };
...@@ -103,10 +111,11 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data, ...@@ -103,10 +111,11 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data,
struct ima_digest_data *hash); struct ima_digest_data *hash);
int __init ima_calc_boot_aggregate(struct ima_digest_data *hash); int __init ima_calc_boot_aggregate(struct ima_digest_data *hash);
void ima_add_violation(struct file *file, const unsigned char *filename, void ima_add_violation(struct file *file, const unsigned char *filename,
struct integrity_iint_cache *iint,
const char *op, const char *cause); const char *op, const char *cause);
int ima_init_crypto(void); int ima_init_crypto(void);
void ima_putc(struct seq_file *m, void *data, int datalen); void ima_putc(struct seq_file *m, void *data, int datalen);
void ima_print_digest(struct seq_file *m, u8 *digest, int size); void ima_print_digest(struct seq_file *m, u8 *digest, u32 size);
struct ima_template_desc *ima_template_desc_current(void); struct ima_template_desc *ima_template_desc_current(void);
int ima_init_template(void); int ima_init_template(void);
...@@ -140,10 +149,8 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, ...@@ -140,10 +149,8 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
int xattr_len); int xattr_len);
void ima_audit_measurement(struct integrity_iint_cache *iint, void ima_audit_measurement(struct integrity_iint_cache *iint,
const unsigned char *filename); const unsigned char *filename);
int ima_alloc_init_template(struct integrity_iint_cache *iint, int ima_alloc_init_template(struct ima_event_data *event_data,
struct file *file, const unsigned char *filename, struct ima_template_entry **entry);
struct evm_ima_xattr_data *xattr_value,
int xattr_len, struct ima_template_entry **entry);
int ima_store_template(struct ima_template_entry *entry, int violation, int ima_store_template(struct ima_template_entry *entry, int violation,
struct inode *inode, const unsigned char *filename); struct inode *inode, const unsigned char *filename);
void ima_free_template_entry(struct ima_template_entry *entry); void ima_free_template_entry(struct ima_template_entry *entry);
......
...@@ -37,10 +37,8 @@ void ima_free_template_entry(struct ima_template_entry *entry) ...@@ -37,10 +37,8 @@ void ima_free_template_entry(struct ima_template_entry *entry)
/* /*
* ima_alloc_init_template - create and initialize a new template entry * ima_alloc_init_template - create and initialize a new template entry
*/ */
int ima_alloc_init_template(struct integrity_iint_cache *iint, int ima_alloc_init_template(struct ima_event_data *event_data,
struct file *file, const unsigned char *filename, struct ima_template_entry **entry)
struct evm_ima_xattr_data *xattr_value,
int xattr_len, struct ima_template_entry **entry)
{ {
struct ima_template_desc *template_desc = ima_template_desc_current(); struct ima_template_desc *template_desc = ima_template_desc_current();
int i, result = 0; int i, result = 0;
...@@ -55,8 +53,7 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint, ...@@ -55,8 +53,7 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint,
struct ima_template_field *field = template_desc->fields[i]; struct ima_template_field *field = template_desc->fields[i];
u32 len; u32 len;
result = field->field_init(iint, file, filename, result = field->field_init(event_data,
xattr_value, xattr_len,
&((*entry)->template_data[i])); &((*entry)->template_data[i]));
if (result != 0) if (result != 0)
goto out; goto out;
...@@ -129,18 +126,20 @@ int ima_store_template(struct ima_template_entry *entry, ...@@ -129,18 +126,20 @@ int ima_store_template(struct ima_template_entry *entry,
* value is invalidated. * value is invalidated.
*/ */
void ima_add_violation(struct file *file, const unsigned char *filename, void ima_add_violation(struct file *file, const unsigned char *filename,
struct integrity_iint_cache *iint,
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_inode(file); struct inode *inode = file_inode(file);
struct ima_event_data event_data = {iint, file, filename, NULL, 0,
cause};
int violation = 1; int violation = 1;
int result; int result;
/* can overflow, only indicator */ /* can overflow, only indicator */
atomic_long_inc(&ima_htable.violations); atomic_long_inc(&ima_htable.violations);
result = ima_alloc_init_template(NULL, file, filename, result = ima_alloc_init_template(&event_data, &entry);
NULL, 0, &entry);
if (result < 0) { if (result < 0) {
result = -ENOMEM; result = -ENOMEM;
goto err_out; goto err_out;
...@@ -267,13 +266,14 @@ void ima_store_measurement(struct integrity_iint_cache *iint, ...@@ -267,13 +266,14 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
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;
struct ima_event_data event_data = {iint, file, filename, xattr_value,
xattr_len, NULL};
int violation = 0; int violation = 0;
if (iint->flags & IMA_MEASURED) if (iint->flags & IMA_MEASURED)
return; return;
result = ima_alloc_init_template(iint, file, filename, result = ima_alloc_init_template(&event_data, &entry);
xattr_value, xattr_len, &entry);
if (result < 0) { if (result < 0) {
integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename, integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
op, audit_cause, result, 0); op, audit_cause, result, 0);
......
...@@ -378,10 +378,14 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, ...@@ -378,10 +378,14 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
result = ima_protect_xattr(dentry, xattr_name, xattr_value, result = ima_protect_xattr(dentry, xattr_name, xattr_value,
xattr_value_len); xattr_value_len);
if (result == 1) { if (result == 1) {
bool digsig;
if (!xattr_value_len || (xvalue->type >= IMA_XATTR_LAST)) if (!xattr_value_len || (xvalue->type >= IMA_XATTR_LAST))
return -EINVAL; return -EINVAL;
ima_reset_appraise_flags(d_backing_inode(dentry), digsig = (xvalue->type == EVM_IMA_XATTR_DIGSIG);
(xvalue->type == EVM_IMA_XATTR_DIGSIG) ? 1 : 0); if (!digsig && (ima_appraise & IMA_APPRAISE_ENFORCE))
return -EPERM;
ima_reset_appraise_flags(d_backing_inode(dentry), digsig);
result = 0; result = 0;
} }
return result; return result;
......
...@@ -190,9 +190,9 @@ static const struct file_operations ima_measurements_ops = { ...@@ -190,9 +190,9 @@ static const struct file_operations ima_measurements_ops = {
.release = seq_release, .release = seq_release,
}; };
void ima_print_digest(struct seq_file *m, u8 *digest, int size) void ima_print_digest(struct seq_file *m, u8 *digest, u32 size)
{ {
int i; u32 i;
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
seq_printf(m, "%02x", *(digest + i)); seq_printf(m, "%02x", *(digest + i));
......
...@@ -24,12 +24,6 @@ ...@@ -24,12 +24,6 @@
#include <crypto/hash_info.h> #include <crypto/hash_info.h>
#include "ima.h" #include "ima.h"
#ifdef CONFIG_IMA_X509_PATH
#define IMA_X509_PATH CONFIG_IMA_X509_PATH
#else
#define IMA_X509_PATH "/etc/keys/x509_ima.der"
#endif
/* name for boot aggregate entry */ /* name for boot aggregate entry */
static const char *boot_aggregate_name = "boot_aggregate"; static const char *boot_aggregate_name = "boot_aggregate";
int ima_used_chip; int ima_used_chip;
...@@ -55,6 +49,8 @@ static int __init ima_add_boot_aggregate(void) ...@@ -55,6 +49,8 @@ static int __init ima_add_boot_aggregate(void)
const char *audit_cause = "ENOMEM"; 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;
struct ima_event_data event_data = {iint, NULL, boot_aggregate_name,
NULL, 0, NULL};
int result = -ENOMEM; int result = -ENOMEM;
int violation = 0; int violation = 0;
struct { struct {
...@@ -76,8 +72,7 @@ static int __init ima_add_boot_aggregate(void) ...@@ -76,8 +72,7 @@ static int __init ima_add_boot_aggregate(void)
} }
} }
result = ima_alloc_init_template(iint, NULL, boot_aggregate_name, result = ima_alloc_init_template(&event_data, &entry);
NULL, 0, &entry);
if (result < 0) { if (result < 0) {
audit_cause = "alloc_entry"; audit_cause = "alloc_entry";
goto err_out; goto err_out;
...@@ -103,7 +98,7 @@ void __init ima_load_x509(void) ...@@ -103,7 +98,7 @@ void __init ima_load_x509(void)
int unset_flags = ima_policy_flag & IMA_APPRAISE; int unset_flags = ima_policy_flag & IMA_APPRAISE;
ima_policy_flag &= ~unset_flags; ima_policy_flag &= ~unset_flags;
integrity_load_x509(INTEGRITY_KEYRING_IMA, IMA_X509_PATH); integrity_load_x509(INTEGRITY_KEYRING_IMA, CONFIG_IMA_X509_PATH);
ima_policy_flag |= unset_flags; ima_policy_flag |= unset_flags;
} }
#endif #endif
......
...@@ -106,9 +106,10 @@ static void ima_rdwr_violation_check(struct file *file, ...@@ -106,9 +106,10 @@ static void ima_rdwr_violation_check(struct file *file,
*pathname = ima_d_path(&file->f_path, pathbuf); *pathname = ima_d_path(&file->f_path, pathbuf);
if (send_tomtou) if (send_tomtou)
ima_add_violation(file, *pathname, "invalid_pcr", "ToMToU"); ima_add_violation(file, *pathname, iint,
"invalid_pcr", "ToMToU");
if (send_writers) if (send_writers)
ima_add_violation(file, *pathname, ima_add_violation(file, *pathname, iint,
"invalid_pcr", "open_writers"); "invalid_pcr", "open_writers");
} }
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#define IMA_UID 0x0008 #define IMA_UID 0x0008
#define IMA_FOWNER 0x0010 #define IMA_FOWNER 0x0010
#define IMA_FSUUID 0x0020 #define IMA_FSUUID 0x0020
#define IMA_INMASK 0x0040
#define IMA_EUID 0x0080
#define UNKNOWN 0 #define UNKNOWN 0
#define MEASURE 0x0001 /* same as IMA_MEASURE */ #define MEASURE 0x0001 /* same as IMA_MEASURE */
...@@ -42,6 +44,8 @@ enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE, ...@@ -42,6 +44,8 @@ enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE
}; };
enum policy_types { ORIGINAL_TCB = 1, DEFAULT_TCB };
struct ima_rule_entry { struct ima_rule_entry {
struct list_head list; struct list_head list;
int action; int action;
...@@ -70,7 +74,7 @@ struct ima_rule_entry { ...@@ -70,7 +74,7 @@ struct ima_rule_entry {
* normal users can easily run the machine out of memory simply building * normal users can easily run the machine out of memory simply building
* and running executables. * and running executables.
*/ */
static struct ima_rule_entry default_rules[] = { static struct ima_rule_entry dont_measure_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},
...@@ -79,12 +83,31 @@ static struct ima_rule_entry default_rules[] = { ...@@ -79,12 +83,31 @@ static struct ima_rule_entry default_rules[] = {
{.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 = DONT_MEASURE, .fsmagic = CGROUP_SUPER_MAGIC,
.flags = IMA_FSMAGIC},
{.action = DONT_MEASURE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC}
};
static struct ima_rule_entry original_measurement_rules[] = {
{.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,
.flags = IMA_FUNC | IMA_MASK | IMA_UID}, .uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_MASK | IMA_UID},
{.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
{.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
};
static struct ima_rule_entry default_measurement_rules[] = {
{.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC,
.flags = IMA_FUNC | IMA_MASK},
{.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC,
.flags = IMA_FUNC | IMA_MASK},
{.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ,
.uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_INMASK | IMA_EUID},
{.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ,
.uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_INMASK | IMA_UID},
{.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC}, {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
{.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC}, {.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
}; };
...@@ -99,6 +122,7 @@ static struct ima_rule_entry default_appraise_rules[] = { ...@@ -99,6 +122,7 @@ static struct ima_rule_entry default_appraise_rules[] = {
{.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 = NSFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC}, {.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC},
#ifndef CONFIG_IMA_APPRAISE_SIGNED_INIT #ifndef CONFIG_IMA_APPRAISE_SIGNED_INIT
{.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .flags = IMA_FOWNER}, {.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .flags = IMA_FOWNER},
...@@ -115,14 +139,29 @@ static struct list_head *ima_rules; ...@@ -115,14 +139,29 @@ static struct list_head *ima_rules;
static DEFINE_MUTEX(ima_rules_mutex); static DEFINE_MUTEX(ima_rules_mutex);
static bool ima_use_tcb __initdata; static int ima_policy __initdata;
static int __init default_measure_policy_setup(char *str) static int __init default_measure_policy_setup(char *str)
{ {
ima_use_tcb = 1; if (ima_policy)
return 1;
ima_policy = ORIGINAL_TCB;
return 1; return 1;
} }
__setup("ima_tcb", default_measure_policy_setup); __setup("ima_tcb", default_measure_policy_setup);
static int __init policy_setup(char *str)
{
if (ima_policy)
return 1;
if (strcmp(str, "tcb") == 0)
ima_policy = DEFAULT_TCB;
return 1;
}
__setup("ima_policy=", policy_setup);
static bool ima_use_appraise_tcb __initdata; static bool ima_use_appraise_tcb __initdata;
static int __init default_appraise_policy_setup(char *str) static int __init default_appraise_policy_setup(char *str)
{ {
...@@ -182,6 +221,9 @@ static bool ima_match_rules(struct ima_rule_entry *rule, ...@@ -182,6 +221,9 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
if ((rule->flags & IMA_MASK) && if ((rule->flags & IMA_MASK) &&
(rule->mask != mask && func != POST_SETATTR)) (rule->mask != mask && func != POST_SETATTR))
return false; return false;
if ((rule->flags & IMA_INMASK) &&
(!(rule->mask & mask) && func != POST_SETATTR))
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)
return false; return false;
...@@ -190,6 +232,16 @@ static bool ima_match_rules(struct ima_rule_entry *rule, ...@@ -190,6 +232,16 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
return false; return false;
if ((rule->flags & IMA_UID) && !uid_eq(rule->uid, cred->uid)) if ((rule->flags & IMA_UID) && !uid_eq(rule->uid, cred->uid))
return false; return false;
if (rule->flags & IMA_EUID) {
if (has_capability_noaudit(current, CAP_SETUID)) {
if (!uid_eq(rule->uid, cred->euid)
&& !uid_eq(rule->uid, cred->suid)
&& !uid_eq(rule->uid, cred->uid))
return false;
} else if (!uid_eq(rule->uid, cred->euid))
return false;
}
if ((rule->flags & IMA_FOWNER) && !uid_eq(rule->fowner, inode->i_uid)) if ((rule->flags & IMA_FOWNER) && !uid_eq(rule->fowner, inode->i_uid))
return false; return false;
for (i = 0; i < MAX_LSM_RULES; i++) { for (i = 0; i < MAX_LSM_RULES; i++) {
...@@ -333,21 +385,31 @@ void __init ima_init_policy(void) ...@@ -333,21 +385,31 @@ void __init ima_init_policy(void)
{ {
int i, measure_entries, appraise_entries; int i, measure_entries, appraise_entries;
/* if !ima_use_tcb set entries = 0 so we load NO default rules */ /* if !ima_policy set entries = 0 so we load NO default rules */
measure_entries = ima_use_tcb ? ARRAY_SIZE(default_rules) : 0; measure_entries = ima_policy ? ARRAY_SIZE(dont_measure_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; i++)
if (i < measure_entries) list_add_tail(&dont_measure_rules[i].list, &ima_default_rules);
list_add_tail(&default_rules[i].list,
&ima_default_rules);
else {
int j = i - measure_entries;
list_add_tail(&default_appraise_rules[j].list, switch (ima_policy) {
case ORIGINAL_TCB:
for (i = 0; i < ARRAY_SIZE(original_measurement_rules); i++)
list_add_tail(&original_measurement_rules[i].list,
&ima_default_rules);
break;
case DEFAULT_TCB:
for (i = 0; i < ARRAY_SIZE(default_measurement_rules); i++)
list_add_tail(&default_measurement_rules[i].list,
&ima_default_rules); &ima_default_rules);
default:
break;
} }
for (i = 0; i < appraise_entries; i++) {
list_add_tail(&default_appraise_rules[i].list,
&ima_default_rules);
} }
ima_rules = &ima_default_rules; ima_rules = &ima_default_rules;
...@@ -373,7 +435,8 @@ enum { ...@@ -373,7 +435,8 @@ enum {
Opt_audit, Opt_audit,
Opt_obj_user, Opt_obj_role, Opt_obj_type, Opt_obj_user, Opt_obj_role, Opt_obj_type,
Opt_subj_user, Opt_subj_role, Opt_subj_type, Opt_subj_user, Opt_subj_role, Opt_subj_type,
Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner, Opt_func, Opt_mask, Opt_fsmagic,
Opt_uid, Opt_euid, Opt_fowner,
Opt_appraise_type, Opt_fsuuid, Opt_permit_directio Opt_appraise_type, Opt_fsuuid, Opt_permit_directio
}; };
...@@ -394,6 +457,7 @@ static match_table_t policy_tokens = { ...@@ -394,6 +457,7 @@ static match_table_t policy_tokens = {
{Opt_fsmagic, "fsmagic=%s"}, {Opt_fsmagic, "fsmagic=%s"},
{Opt_fsuuid, "fsuuid=%s"}, {Opt_fsuuid, "fsuuid=%s"},
{Opt_uid, "uid=%s"}, {Opt_uid, "uid=%s"},
{Opt_euid, "euid=%s"},
{Opt_fowner, "fowner=%s"}, {Opt_fowner, "fowner=%s"},
{Opt_appraise_type, "appraise_type=%s"}, {Opt_appraise_type, "appraise_type=%s"},
{Opt_permit_directio, "permit_directio"}, {Opt_permit_directio, "permit_directio"},
...@@ -435,6 +499,7 @@ static void ima_log_string(struct audit_buffer *ab, char *key, char *value) ...@@ -435,6 +499,7 @@ static void ima_log_string(struct audit_buffer *ab, char *key, char *value)
static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
{ {
struct audit_buffer *ab; struct audit_buffer *ab;
char *from;
char *p; char *p;
int result = 0; int result = 0;
...@@ -525,18 +590,23 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) ...@@ -525,18 +590,23 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
if (entry->mask) if (entry->mask)
result = -EINVAL; result = -EINVAL;
if ((strcmp(args[0].from, "MAY_EXEC")) == 0) from = args[0].from;
if (*from == '^')
from++;
if ((strcmp(from, "MAY_EXEC")) == 0)
entry->mask = MAY_EXEC; entry->mask = MAY_EXEC;
else if (strcmp(args[0].from, "MAY_WRITE") == 0) else if (strcmp(from, "MAY_WRITE") == 0)
entry->mask = MAY_WRITE; entry->mask = MAY_WRITE;
else if (strcmp(args[0].from, "MAY_READ") == 0) else if (strcmp(from, "MAY_READ") == 0)
entry->mask = MAY_READ; entry->mask = MAY_READ;
else if (strcmp(args[0].from, "MAY_APPEND") == 0) else if (strcmp(from, "MAY_APPEND") == 0)
entry->mask = MAY_APPEND; entry->mask = MAY_APPEND;
else else
result = -EINVAL; result = -EINVAL;
if (!result) if (!result)
entry->flags |= IMA_MASK; entry->flags |= (*args[0].from == '^')
? IMA_INMASK : IMA_MASK;
break; break;
case Opt_fsmagic: case Opt_fsmagic:
ima_log_string(ab, "fsmagic", args[0].from); ima_log_string(ab, "fsmagic", args[0].from);
...@@ -566,6 +636,9 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) ...@@ -566,6 +636,9 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
break; break;
case Opt_uid: case Opt_uid:
ima_log_string(ab, "uid", args[0].from); ima_log_string(ab, "uid", args[0].from);
case Opt_euid:
if (token == Opt_euid)
ima_log_string(ab, "euid", args[0].from);
if (uid_valid(entry->uid)) { if (uid_valid(entry->uid)) {
result = -EINVAL; result = -EINVAL;
...@@ -574,11 +647,14 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) ...@@ -574,11 +647,14 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
result = kstrtoul(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(),
if (!uid_valid(entry->uid) || (((uid_t)lnum) != lnum)) (uid_t) lnum);
if (!uid_valid(entry->uid) ||
(uid_t)lnum != lnum)
result = -EINVAL; result = -EINVAL;
else else
entry->flags |= IMA_UID; entry->flags |= (token == Opt_uid)
? IMA_UID : IMA_EUID;
} }
break; break;
case Opt_fowner: case Opt_fowner:
......
...@@ -70,7 +70,8 @@ static void ima_show_template_data_ascii(struct seq_file *m, ...@@ -70,7 +70,8 @@ static void ima_show_template_data_ascii(struct seq_file *m,
enum data_formats datafmt, enum data_formats datafmt,
struct ima_field_data *field_data) struct ima_field_data *field_data)
{ {
u8 *buf_ptr = field_data->data, buflen = field_data->len; u8 *buf_ptr = field_data->data;
u32 buflen = field_data->len;
switch (datafmt) { switch (datafmt) {
case DATA_FMT_DIGEST_WITH_ALGO: case DATA_FMT_DIGEST_WITH_ALGO:
...@@ -195,9 +196,7 @@ static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo, ...@@ -195,9 +196,7 @@ static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo,
/* /*
* This function writes the digest of an event (with size limit). * This function writes the digest of an event (with size limit).
*/ */
int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file, int ima_eventdigest_init(struct ima_event_data *event_data,
const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value, int xattr_len,
struct ima_field_data *field_data) struct ima_field_data *field_data)
{ {
struct { struct {
...@@ -211,25 +210,25 @@ int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file, ...@@ -211,25 +210,25 @@ int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
memset(&hash, 0, sizeof(hash)); memset(&hash, 0, sizeof(hash));
if (!iint) /* recording a violation. */ if (event_data->violation) /* recording a violation. */
goto out; goto out;
if (ima_template_hash_algo_allowed(iint->ima_hash->algo)) { if (ima_template_hash_algo_allowed(event_data->iint->ima_hash->algo)) {
cur_digest = iint->ima_hash->digest; cur_digest = event_data->iint->ima_hash->digest;
cur_digestsize = iint->ima_hash->length; cur_digestsize = event_data->iint->ima_hash->length;
goto out; goto out;
} }
if (!file) /* missing info to re-calculate the digest */ if (!event_data->file) /* missing info to re-calculate the digest */
return -EINVAL; return -EINVAL;
inode = file_inode(file); inode = file_inode(event_data->file);
hash.hdr.algo = ima_template_hash_algo_allowed(ima_hash_algo) ? hash.hdr.algo = ima_template_hash_algo_allowed(ima_hash_algo) ?
ima_hash_algo : HASH_ALGO_SHA1; ima_hash_algo : HASH_ALGO_SHA1;
result = ima_calc_file_hash(file, &hash.hdr); result = ima_calc_file_hash(event_data->file, &hash.hdr);
if (result) { if (result) {
integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
filename, "collect_data", event_data->filename, "collect_data",
"failed", result, 0); "failed", result, 0);
return result; return result;
} }
...@@ -243,48 +242,43 @@ int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file, ...@@ -243,48 +242,43 @@ int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
/* /*
* This function writes the digest of an event (without size limit). * This function writes the digest of an event (without size limit).
*/ */
int ima_eventdigest_ng_init(struct integrity_iint_cache *iint, int ima_eventdigest_ng_init(struct ima_event_data *event_data,
struct file *file, const unsigned char *filename, struct ima_field_data *field_data)
struct evm_ima_xattr_data *xattr_value,
int xattr_len, struct ima_field_data *field_data)
{ {
u8 *cur_digest = NULL, hash_algo = HASH_ALGO_SHA1; u8 *cur_digest = NULL, hash_algo = HASH_ALGO_SHA1;
u32 cur_digestsize = 0; u32 cur_digestsize = 0;
/* If iint is NULL, we are recording a violation. */ if (event_data->violation) /* recording a violation. */
if (!iint)
goto out; goto out;
cur_digest = iint->ima_hash->digest; cur_digest = event_data->iint->ima_hash->digest;
cur_digestsize = iint->ima_hash->length; cur_digestsize = event_data->iint->ima_hash->length;
hash_algo = iint->ima_hash->algo; hash_algo = event_data->iint->ima_hash->algo;
out: out:
return ima_eventdigest_init_common(cur_digest, cur_digestsize, return ima_eventdigest_init_common(cur_digest, cur_digestsize,
hash_algo, field_data); hash_algo, field_data);
} }
static int ima_eventname_init_common(struct integrity_iint_cache *iint, static int ima_eventname_init_common(struct ima_event_data *event_data,
struct file *file,
const unsigned char *filename,
struct ima_field_data *field_data, struct ima_field_data *field_data,
bool size_limit) bool size_limit)
{ {
const char *cur_filename = NULL; const char *cur_filename = NULL;
u32 cur_filename_len = 0; u32 cur_filename_len = 0;
BUG_ON(filename == NULL && file == NULL); BUG_ON(event_data->filename == NULL && event_data->file == NULL);
if (filename) { if (event_data->filename) {
cur_filename = filename; cur_filename = event_data->filename;
cur_filename_len = strlen(filename); cur_filename_len = strlen(event_data->filename);
if (!size_limit || cur_filename_len <= IMA_EVENT_NAME_LEN_MAX) if (!size_limit || cur_filename_len <= IMA_EVENT_NAME_LEN_MAX)
goto out; goto out;
} }
if (file) { if (event_data->file) {
cur_filename = file->f_path.dentry->d_name.name; cur_filename = event_data->file->f_path.dentry->d_name.name;
cur_filename_len = strlen(cur_filename); cur_filename_len = strlen(cur_filename);
} else } else
/* /*
...@@ -300,36 +294,30 @@ static int ima_eventname_init_common(struct integrity_iint_cache *iint, ...@@ -300,36 +294,30 @@ static int ima_eventname_init_common(struct integrity_iint_cache *iint,
/* /*
* This function writes the name of an event (with size limit). * This function writes the name of an event (with size limit).
*/ */
int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file, int ima_eventname_init(struct ima_event_data *event_data,
const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value, int xattr_len,
struct ima_field_data *field_data) struct ima_field_data *field_data)
{ {
return ima_eventname_init_common(iint, file, filename, return ima_eventname_init_common(event_data, field_data, true);
field_data, true);
} }
/* /*
* This function writes the name of an event (without size limit). * This function writes the name of an event (without size limit).
*/ */
int ima_eventname_ng_init(struct integrity_iint_cache *iint, struct file *file, int ima_eventname_ng_init(struct ima_event_data *event_data,
const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value, int xattr_len,
struct ima_field_data *field_data) struct ima_field_data *field_data)
{ {
return ima_eventname_init_common(iint, file, filename, return ima_eventname_init_common(event_data, field_data, false);
field_data, false);
} }
/* /*
* ima_eventsig_init - include the file signature as part of the template data * ima_eventsig_init - include the file signature as part of the template data
*/ */
int ima_eventsig_init(struct integrity_iint_cache *iint, struct file *file, int ima_eventsig_init(struct ima_event_data *event_data,
const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value, int xattr_len,
struct ima_field_data *field_data) struct ima_field_data *field_data)
{ {
enum data_formats fmt = DATA_FMT_HEX; enum data_formats fmt = DATA_FMT_HEX;
struct evm_ima_xattr_data *xattr_value = event_data->xattr_value;
int xattr_len = event_data->xattr_len;
int rc = 0; int rc = 0;
if ((!xattr_value) || (xattr_value->type != EVM_IMA_XATTR_DIGSIG)) if ((!xattr_value) || (xattr_value->type != EVM_IMA_XATTR_DIGSIG))
......
...@@ -26,24 +26,14 @@ void ima_show_template_string(struct seq_file *m, enum ima_show_type show, ...@@ -26,24 +26,14 @@ void ima_show_template_string(struct seq_file *m, enum ima_show_type show,
struct ima_field_data *field_data); struct ima_field_data *field_data);
void ima_show_template_sig(struct seq_file *m, enum ima_show_type show, void ima_show_template_sig(struct seq_file *m, enum ima_show_type show,
struct ima_field_data *field_data); struct ima_field_data *field_data);
int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file, int ima_eventdigest_init(struct ima_event_data *event_data,
const unsigned char *filename, struct ima_field_data *field_data);
struct evm_ima_xattr_data *xattr_value, int xattr_len, int ima_eventname_init(struct ima_event_data *event_data,
struct ima_field_data *field_data); struct ima_field_data *field_data);
int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file, int ima_eventdigest_ng_init(struct ima_event_data *event_data,
const unsigned char *filename, struct ima_field_data *field_data);
struct evm_ima_xattr_data *xattr_value, int xattr_len, int ima_eventname_ng_init(struct ima_event_data *event_data,
struct ima_field_data *field_data); struct ima_field_data *field_data);
int ima_eventdigest_ng_init(struct integrity_iint_cache *iint, int ima_eventsig_init(struct ima_event_data *event_data,
struct file *file, const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value,
int xattr_len, struct ima_field_data *field_data);
int ima_eventname_ng_init(struct integrity_iint_cache *iint, struct file *file,
const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value, int xattr_len,
struct ima_field_data *field_data);
int ima_eventsig_init(struct integrity_iint_cache *iint, struct file *file,
const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value, int xattr_len,
struct ima_field_data *field_data); struct ima_field_data *field_data);
#endif /* __LINUX_IMA_TEMPLATE_LIB_H */ #endif /* __LINUX_IMA_TEMPLATE_LIB_H */
...@@ -135,7 +135,7 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, ...@@ -135,7 +135,7 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
const char *digest, int digestlen); const char *digest, int digestlen);
int __init integrity_init_keyring(const unsigned int id); int __init integrity_init_keyring(const unsigned int id);
int __init integrity_load_x509(const unsigned int id, char *path); int __init integrity_load_x509(const unsigned int id, const char *path);
#else #else
static inline int integrity_digsig_verify(const unsigned int id, static inline int integrity_digsig_verify(const unsigned int id,
......
This diff is collapsed.
This diff is collapsed.
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
"getattr", "setattr", "lock", "relabelfrom", "relabelto", "append" "getattr", "setattr", "lock", "relabelfrom", "relabelto", "append"
#define COMMON_FILE_PERMS COMMON_FILE_SOCK_PERMS, "unlink", "link", \ #define COMMON_FILE_PERMS COMMON_FILE_SOCK_PERMS, "unlink", "link", \
"rename", "execute", "swapon", "quotaon", "mounton", "audit_access", \ "rename", "execute", "quotaon", "mounton", "audit_access", \
"open", "execmod" "open", "execmod"
#define COMMON_SOCK_PERMS COMMON_FILE_SOCK_PERMS, "bind", "connect", \ #define COMMON_SOCK_PERMS COMMON_FILE_SOCK_PERMS, "bind", "connect", \
"listen", "accept", "getopt", "setopt", "shutdown", "recvfrom", \ "listen", "accept", "getopt", "setopt", "shutdown", "recvfrom", \
"sendto", "recv_msg", "send_msg", "name_bind" "sendto", "name_bind"
#define COMMON_IPC_PERMS "create", "destroy", "getattr", "setattr", "read", \ #define COMMON_IPC_PERMS "create", "destroy", "getattr", "setattr", "read", \
"write", "associate", "unix_read", "unix_write" "write", "associate", "unix_read", "unix_write"
...@@ -44,7 +44,7 @@ struct security_class_mapping secclass_map[] = { ...@@ -44,7 +44,7 @@ struct security_class_mapping secclass_map[] = {
"audit_control", "setfcap", NULL } }, "audit_control", "setfcap", NULL } },
{ "filesystem", { "filesystem",
{ "mount", "remount", "unmount", "getattr", { "mount", "remount", "unmount", "getattr",
"relabelfrom", "relabelto", "transition", "associate", "quotamod", "relabelfrom", "relabelto", "associate", "quotamod",
"quotaget", NULL } }, "quotaget", NULL } },
{ "file", { "file",
{ COMMON_FILE_PERMS, { COMMON_FILE_PERMS,
...@@ -67,7 +67,7 @@ struct security_class_mapping secclass_map[] = { ...@@ -67,7 +67,7 @@ struct security_class_mapping secclass_map[] = {
{ COMMON_SOCK_PERMS, NULL } }, { COMMON_SOCK_PERMS, NULL } },
{ "tcp_socket", { "tcp_socket",
{ COMMON_SOCK_PERMS, { COMMON_SOCK_PERMS,
"connectto", "newconn", "acceptfrom", "node_bind", "name_connect", "node_bind", "name_connect",
NULL } }, NULL } },
{ "udp_socket", { "udp_socket",
{ COMMON_SOCK_PERMS, { COMMON_SOCK_PERMS,
...@@ -76,13 +76,9 @@ struct security_class_mapping secclass_map[] = { ...@@ -76,13 +76,9 @@ struct security_class_mapping secclass_map[] = {
{ COMMON_SOCK_PERMS, { COMMON_SOCK_PERMS,
"node_bind", NULL } }, "node_bind", NULL } },
{ "node", { "node",
{ "tcp_recv", "tcp_send", "udp_recv", "udp_send", { "recvfrom", "sendto", NULL } },
"rawip_recv", "rawip_send", "enforce_dest",
"dccp_recv", "dccp_send", "recvfrom", "sendto", NULL } },
{ "netif", { "netif",
{ "tcp_recv", "tcp_send", "udp_recv", "udp_send", { "ingress", "egress", NULL } },
"rawip_recv", "rawip_send", "dccp_recv", "dccp_send",
"ingress", "egress", NULL } },
{ "netlink_socket", { "netlink_socket",
{ COMMON_SOCK_PERMS, NULL } }, { COMMON_SOCK_PERMS, NULL } },
{ "packet_socket", { "packet_socket",
...@@ -90,11 +86,9 @@ struct security_class_mapping secclass_map[] = { ...@@ -90,11 +86,9 @@ struct security_class_mapping secclass_map[] = {
{ "key_socket", { "key_socket",
{ COMMON_SOCK_PERMS, NULL } }, { COMMON_SOCK_PERMS, NULL } },
{ "unix_stream_socket", { "unix_stream_socket",
{ COMMON_SOCK_PERMS, "connectto", "newconn", "acceptfrom", NULL { COMMON_SOCK_PERMS, "connectto", NULL } },
} },
{ "unix_dgram_socket", { "unix_dgram_socket",
{ COMMON_SOCK_PERMS, NULL { COMMON_SOCK_PERMS, NULL } },
} },
{ "sem", { "sem",
{ COMMON_IPC_PERMS, NULL } }, { COMMON_IPC_PERMS, NULL } },
{ "msg", { "send", "receive", NULL } }, { "msg", { "send", "receive", NULL } },
...@@ -107,9 +101,6 @@ struct security_class_mapping secclass_map[] = { ...@@ -107,9 +101,6 @@ struct security_class_mapping secclass_map[] = {
{ "netlink_route_socket", { "netlink_route_socket",
{ COMMON_SOCK_PERMS, { COMMON_SOCK_PERMS,
"nlmsg_read", "nlmsg_write", NULL } }, "nlmsg_read", "nlmsg_write", NULL } },
{ "netlink_firewall_socket",
{ COMMON_SOCK_PERMS,
"nlmsg_read", "nlmsg_write", NULL } },
{ "netlink_tcpdiag_socket", { "netlink_tcpdiag_socket",
{ COMMON_SOCK_PERMS, { COMMON_SOCK_PERMS,
"nlmsg_read", "nlmsg_write", NULL } }, "nlmsg_read", "nlmsg_write", NULL } },
...@@ -120,19 +111,32 @@ struct security_class_mapping secclass_map[] = { ...@@ -120,19 +111,32 @@ struct security_class_mapping secclass_map[] = {
"nlmsg_read", "nlmsg_write", NULL } }, "nlmsg_read", "nlmsg_write", NULL } },
{ "netlink_selinux_socket", { "netlink_selinux_socket",
{ COMMON_SOCK_PERMS, NULL } }, { COMMON_SOCK_PERMS, NULL } },
{ "netlink_iscsi_socket",
{ COMMON_SOCK_PERMS, NULL } },
{ "netlink_audit_socket", { "netlink_audit_socket",
{ COMMON_SOCK_PERMS, { COMMON_SOCK_PERMS,
"nlmsg_read", "nlmsg_write", "nlmsg_relay", "nlmsg_readpriv", "nlmsg_read", "nlmsg_write", "nlmsg_relay", "nlmsg_readpriv",
"nlmsg_tty_audit", NULL } }, "nlmsg_tty_audit", NULL } },
{ "netlink_ip6fw_socket", { "netlink_fib_lookup_socket",
{ COMMON_SOCK_PERMS, { COMMON_SOCK_PERMS, NULL } },
"nlmsg_read", "nlmsg_write", NULL } }, { "netlink_connector_socket",
{ COMMON_SOCK_PERMS, NULL } },
{ "netlink_netfilter_socket",
{ COMMON_SOCK_PERMS, NULL } },
{ "netlink_dnrt_socket", { "netlink_dnrt_socket",
{ COMMON_SOCK_PERMS, NULL } }, { COMMON_SOCK_PERMS, NULL } },
{ "association", { "association",
{ "sendto", "recvfrom", "setcontext", "polmatch", NULL } }, { "sendto", "recvfrom", "setcontext", "polmatch", NULL } },
{ "netlink_kobject_uevent_socket", { "netlink_kobject_uevent_socket",
{ COMMON_SOCK_PERMS, NULL } }, { COMMON_SOCK_PERMS, NULL } },
{ "netlink_generic_socket",
{ COMMON_SOCK_PERMS, NULL } },
{ "netlink_scsitransport_socket",
{ COMMON_SOCK_PERMS, NULL } },
{ "netlink_rdma_socket",
{ COMMON_SOCK_PERMS, NULL } },
{ "netlink_crypto_socket",
{ COMMON_SOCK_PERMS, NULL } },
{ "appletalk_socket", { "appletalk_socket",
{ COMMON_SOCK_PERMS, NULL } }, { COMMON_SOCK_PERMS, NULL } },
{ "packet", { "packet",
......
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
/* Non-mount related flags */ /* Non-mount related flags */
#define SE_SBINITIALIZED 0x0100 #define SE_SBINITIALIZED 0x0100
#define SE_SBPROC 0x0200 #define SE_SBPROC 0x0200
#define SE_SBGENFS 0x0400
#define CONTEXT_STR "context=" #define CONTEXT_STR "context="
#define FSCONTEXT_STR "fscontext=" #define FSCONTEXT_STR "fscontext="
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#include <linux/capability.h> #include <linux/capability.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/security.h> #include <linux/lsm_hooks.h>
#include <linux/in.h> #include <linux/in.h>
#include <net/netlabel.h> #include <net/netlabel.h>
#include <linux/list.h> #include <linux/list.h>
...@@ -138,6 +138,11 @@ struct smk_port_label { ...@@ -138,6 +138,11 @@ struct smk_port_label {
struct smack_known *smk_out; /* outgoing label */ struct smack_known *smk_out; /* outgoing label */
}; };
struct smack_onlycap {
struct list_head list;
struct smack_known *smk_label;
};
/* /*
* Mount options * Mount options
*/ */
...@@ -249,6 +254,7 @@ int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int); ...@@ -249,6 +254,7 @@ int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int);
struct smack_known *smk_import_entry(const char *, int); struct smack_known *smk_import_entry(const char *, int);
void smk_insert_entry(struct smack_known *skp); void smk_insert_entry(struct smack_known *skp);
struct smack_known *smk_find_entry(const char *); struct smack_known *smk_find_entry(const char *);
int smack_privileged(int cap);
/* /*
* Shared data. * Shared data.
...@@ -257,7 +263,6 @@ extern int smack_enabled; ...@@ -257,7 +263,6 @@ extern int smack_enabled;
extern int smack_cipso_direct; extern int smack_cipso_direct;
extern int smack_cipso_mapped; extern int smack_cipso_mapped;
extern struct smack_known *smack_net_ambient; extern struct smack_known *smack_net_ambient;
extern struct smack_known *smack_onlycap;
extern struct smack_known *smack_syslog_label; extern struct smack_known *smack_syslog_label;
#ifdef CONFIG_SECURITY_SMACK_BRINGUP #ifdef CONFIG_SECURITY_SMACK_BRINGUP
extern struct smack_known *smack_unconfined; extern struct smack_known *smack_unconfined;
...@@ -276,7 +281,8 @@ extern struct mutex smack_known_lock; ...@@ -276,7 +281,8 @@ extern struct mutex smack_known_lock;
extern struct list_head smack_known_list; extern struct list_head smack_known_list;
extern struct list_head smk_netlbladdr_list; extern struct list_head smk_netlbladdr_list;
extern struct security_operations smack_ops; extern struct mutex smack_onlycap_lock;
extern struct list_head smack_onlycap_list;
#define SMACK_HASH_SLOTS 16 #define SMACK_HASH_SLOTS 16
extern struct hlist_head smack_known_hash[SMACK_HASH_SLOTS]; extern struct hlist_head smack_known_hash[SMACK_HASH_SLOTS];
...@@ -333,21 +339,6 @@ static inline struct smack_known *smk_of_current(void) ...@@ -333,21 +339,6 @@ static inline struct smack_known *smk_of_current(void)
return smk_of_task(current_security()); return smk_of_task(current_security());
} }
/*
* Is the task privileged and allowed to be privileged
* by the onlycap rule.
*/
static inline int smack_privileged(int cap)
{
struct smack_known *skp = smk_of_current();
if (!capable(cap))
return 0;
if (smack_onlycap == NULL || smack_onlycap == skp)
return 1;
return 0;
}
/* /*
* logging functions * logging functions
*/ */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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