Commit c9341ee0 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 layer updates from James Morris:
 "Highlights:

   - major AppArmor update: policy namespaces & lots of fixes

   - add /sys/kernel/security/lsm node for easy detection of loaded LSMs

   - SELinux cgroupfs labeling support

   - SELinux context mounts on tmpfs, ramfs, devpts within user
     namespaces

   - improved TPM 2.0 support"

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (117 commits)
  tpm: declare tpm2_get_pcr_allocation() as static
  tpm: Fix expected number of response bytes of TPM1.2 PCR Extend
  tpm xen: drop unneeded chip variable
  tpm: fix misspelled "facilitate" in module parameter description
  tpm_tis: fix the error handling of init_tis()
  KEYS: Use memzero_explicit() for secret data
  KEYS: Fix an error code in request_master_key()
  sign-file: fix build error in sign-file.c with libressl
  selinux: allow changing labels for cgroupfs
  selinux: fix off-by-one in setprocattr
  tpm: silence an array overflow warning
  tpm: fix the type of owned field in cap_t
  tpm: add securityfs support for TPM 2.0 firmware event log
  tpm: enhance read_log_of() to support Physical TPM event log
  tpm: enhance TPM 2.0 PCR extend to support multiple banks
  tpm: implement TPM 2.0 capability to get active PCR banks
  tpm: fix RC value check in tpm2_seal_trusted
  tpm_tis: fix iTPM probe via probe_itpm() function
  tpm: Begin the process to deprecate user_read_timer
  tpm: remove tpm_read_index and tpm_write_index from tpm.h
  ...
parents 7a771cea 61841be6
......@@ -22,6 +22,13 @@ system, building their checks on top of the defined capability hooks.
For more details on capabilities, see capabilities(7) in the Linux
man-pages project.
A list of the active security modules can be found by reading
/sys/kernel/security/lsm. This is a comma separated list, and
will always include the capability module. The list reflects the
order in which checks are made. The capability module will always
be first, followed by any "minor" modules (e.g. Yama) and then
the one "major" module (e.g. SELinux) if there is one configured.
Based on https://lkml.org/lkml/2007/10/26/215,
a new LSM is accepted into the kernel when its intent (a description of
what it tries to protect against and in what cases one would expect to
......
......@@ -6,6 +6,7 @@ menuconfig TCG_TPM
tristate "TPM Hardware Support"
depends on HAS_IOMEM
select SECURITYFS
select CRYPTO_HASH_INFO
---help---
If you have a TPM security chip in your system, which
implements the Trusted Computing Group's specification,
......
......@@ -3,7 +3,7 @@
#
obj-$(CONFIG_TCG_TPM) += tpm.o
tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \
tpm_eventlog.o
tpm1_eventlog.o tpm2_eventlog.o
tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_acpi.o
tpm-$(CONFIG_OF) += tpm_of.o
obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
......
......@@ -18,7 +18,6 @@
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/wait.h>
......
......@@ -141,7 +141,7 @@ static void tpm_dev_release(struct device *dev)
* Allocates a new struct tpm_chip instance and assigns a free
* device number for it. Must be paired with put_device(&chip->dev).
*/
struct tpm_chip *tpm_chip_alloc(struct device *dev,
struct tpm_chip *tpm_chip_alloc(struct device *pdev,
const struct tpm_class_ops *ops)
{
struct tpm_chip *chip;
......@@ -160,7 +160,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *dev,
rc = idr_alloc(&dev_nums_idr, NULL, 0, TPM_NUM_DEVICES, GFP_KERNEL);
mutex_unlock(&idr_lock);
if (rc < 0) {
dev_err(dev, "No available tpm device numbers\n");
dev_err(pdev, "No available tpm device numbers\n");
kfree(chip);
return ERR_PTR(rc);
}
......@@ -170,7 +170,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *dev,
chip->dev.class = tpm_class;
chip->dev.release = tpm_dev_release;
chip->dev.parent = dev;
chip->dev.parent = pdev;
chip->dev.groups = chip->groups;
if (chip->dev_num == 0)
......@@ -182,7 +182,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *dev,
if (rc)
goto out;
if (!dev)
if (!pdev)
chip->flags |= TPM_CHIP_FLAG_VIRTUAL;
cdev_init(&chip->cdev, &tpm_fops);
......
......@@ -38,6 +38,9 @@ static void user_reader_timeout(unsigned long ptr)
{
struct file_priv *priv = (struct file_priv *)ptr;
pr_warn("TPM user space timeout is deprecated (pid=%d)\n",
task_tgid_nr(current));
schedule_work(&priv->work);
}
......@@ -157,7 +160,7 @@ static ssize_t tpm_write(struct file *file, const char __user *buf,
mutex_unlock(&priv->buffer_mutex);
/* Set a timeout by which the reader must come claim the result */
mod_timer(&priv->user_read_timer, jiffies + (60 * HZ));
mod_timer(&priv->user_read_timer, jiffies + (120 * HZ));
return in_size;
}
......
This diff is collapsed.
......@@ -21,6 +21,7 @@
#include "tpm.h"
#define READ_PUBEK_RESULT_SIZE 314
#define READ_PUBEK_RESULT_MIN_BODY_SIZE (28 + 256)
#define TPM_ORD_READPUBEK cpu_to_be32(124)
static const struct tpm_input_header tpm_readpubek_header = {
.tag = TPM_TAG_RQU_COMMAND,
......@@ -39,7 +40,8 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
struct tpm_chip *chip = to_tpm_chip(dev);
tpm_cmd.header.in = tpm_readpubek_header;
err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, 0,
err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
READ_PUBEK_RESULT_MIN_BODY_SIZE, 0,
"attempting to read the PUBEK");
if (err)
goto out;
......@@ -95,7 +97,8 @@ static ssize_t pcrs_show(struct device *dev, struct device_attribute *attr,
struct tpm_chip *chip = to_tpm_chip(dev);
rc = tpm_getcap(chip, TPM_CAP_PROP_PCR, &cap,
"attempting to determine the number of PCRS");
"attempting to determine the number of PCRS",
sizeof(cap.num_pcrs));
if (rc)
return 0;
......@@ -120,7 +123,8 @@ static ssize_t enabled_show(struct device *dev, struct device_attribute *attr,
ssize_t rc;
rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap,
"attempting to determine the permanent enabled state");
"attempting to determine the permanent enabled state",
sizeof(cap.perm_flags));
if (rc)
return 0;
......@@ -136,7 +140,8 @@ static ssize_t active_show(struct device *dev, struct device_attribute *attr,
ssize_t rc;
rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap,
"attempting to determine the permanent active state");
"attempting to determine the permanent active state",
sizeof(cap.perm_flags));
if (rc)
return 0;
......@@ -152,7 +157,8 @@ static ssize_t owned_show(struct device *dev, struct device_attribute *attr,
ssize_t rc;
rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_PROP_OWNER, &cap,
"attempting to determine the owner state");
"attempting to determine the owner state",
sizeof(cap.owned));
if (rc)
return 0;
......@@ -168,7 +174,8 @@ static ssize_t temp_deactivated_show(struct device *dev,
ssize_t rc;
rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_VOL, &cap,
"attempting to determine the temporary state");
"attempting to determine the temporary state",
sizeof(cap.stclear_flags));
if (rc)
return 0;
......@@ -186,7 +193,8 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr,
char *str = buf;
rc = tpm_getcap(chip, TPM_CAP_PROP_MANUFACTURER, &cap,
"attempting to determine the manufacturer");
"attempting to determine the manufacturer",
sizeof(cap.manufacturer_id));
if (rc)
return 0;
str += sprintf(str, "Manufacturer: 0x%x\n",
......@@ -194,7 +202,8 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr,
/* Try to get a TPM version 1.2 TPM_CAP_VERSION_INFO */
rc = tpm_getcap(chip, TPM_CAP_VERSION_1_2, &cap,
"attempting to determine the 1.2 version");
"attempting to determine the 1.2 version",
sizeof(cap.tpm_version_1_2));
if (!rc) {
str += sprintf(str,
"TCG version: %d.%d\nFirmware version: %d.%d\n",
......@@ -205,7 +214,8 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr,
} else {
/* Otherwise just use TPM_STRUCT_VER */
rc = tpm_getcap(chip, TPM_CAP_VERSION_1_1, &cap,
"attempting to determine the 1.1 version");
"attempting to determine the 1.1 version",
sizeof(cap.tpm_version));
if (rc)
return 0;
str += sprintf(str,
......
......@@ -34,8 +34,7 @@
#include <linux/acpi.h>
#include <linux/cdev.h>
#include <linux/highmem.h>
#include "tpm_eventlog.h"
#include <crypto/hash_info.h>
enum tpm_const {
TPM_MINOR = 224, /* officially assigned */
......@@ -97,6 +96,7 @@ enum tpm2_return_codes {
};
enum tpm2_algorithms {
TPM2_ALG_ERROR = 0x0000,
TPM2_ALG_SHA1 = 0x0004,
TPM2_ALG_KEYEDHASH = 0x0008,
TPM2_ALG_SHA256 = 0x000B,
......@@ -127,6 +127,7 @@ enum tpm2_permanent_handles {
};
enum tpm2_capabilities {
TPM2_CAP_PCRS = 5,
TPM2_CAP_TPM_PROPERTIES = 6,
};
......@@ -148,6 +149,11 @@ enum tpm_chip_flags {
TPM_CHIP_FLAG_HAVE_TIMEOUTS = BIT(4),
};
struct tpm_bios_log {
void *bios_event_log;
void *bios_event_log_end;
};
struct tpm_chip_seqops {
struct tpm_chip *chip;
const struct seq_operations *seqops;
......@@ -187,6 +193,8 @@ struct tpm_chip {
const struct attribute_group *groups[3];
unsigned int groups_cnt;
u16 active_banks[7];
#ifdef CONFIG_ACPI
acpi_handle acpi_dev_handle;
char ppi_version[TPM_PPI_VERSION_LEN + 1];
......@@ -195,17 +203,6 @@ struct tpm_chip {
#define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
static inline int tpm_read_index(int base, int index)
{
outb(index, base);
return inb(base+1) & 0xFF;
}
static inline void tpm_write_index(int base, int index, int value)
{
outb(index, base);
outb(value & 0xFF, base+1);
}
struct tpm_input_header {
__be16 tag;
__be32 length;
......@@ -284,7 +281,7 @@ struct permanent_flags_t {
typedef union {
struct permanent_flags_t perm_flags;
struct stclear_flags_t stclear_flags;
bool owned;
__u8 owned;
__be32 num_pcrs;
struct tpm_version_t tpm_version;
struct tpm_version_1_2_t tpm_version_1_2;
......@@ -387,6 +384,11 @@ struct tpm_cmd_t {
tpm_cmd_params params;
} __packed;
struct tpm2_digest {
u16 alg_id;
u8 digest[SHA512_DIGEST_SIZE];
} __packed;
/* A string buffer type for constructing TPM commands. This is based on the
* ideas of string buffer code in security/keys/trusted.h but is heap based
* in order to keep the stack usage minimal.
......@@ -493,10 +495,11 @@ enum tpm_transmit_flags {
ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
unsigned int flags);
ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *cmd, int len,
unsigned int flags, const char *desc);
ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *buf, size_t bufsiz,
size_t min_rsp_body_len, unsigned int flags,
const char *desc);
ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
const char *desc, size_t min_cap_length);
int tpm_get_timeouts(struct tpm_chip *);
int tpm1_auto_startup(struct tpm_chip *chip);
int tpm_do_selftest(struct tpm_chip *chip);
......@@ -529,8 +532,14 @@ static inline void tpm_add_ppi(struct tpm_chip *chip)
}
#endif
static inline inline u32 tpm2_rc_value(u32 rc)
{
return (rc & BIT(7)) ? rc & 0xff : rc;
}
int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash);
int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count,
struct tpm2_digest *digests);
int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max);
int tpm2_seal_trusted(struct tpm_chip *chip,
struct trusted_key_payload *payload,
......
......@@ -390,9 +390,6 @@ int tpm_bios_log_setup(struct tpm_chip *chip)
unsigned int cnt;
int rc = 0;
if (chip->flags & TPM_CHIP_FLAG_TPM2)
return 0;
rc = tpm_read_log(chip);
if (rc)
return rc;
......@@ -407,7 +404,13 @@ int tpm_bios_log_setup(struct tpm_chip *chip)
cnt++;
chip->bin_log_seqops.chip = chip;
chip->bin_log_seqops.seqops = &tpm_binary_b_measurements_seqops;
if (chip->flags & TPM_CHIP_FLAG_TPM2)
chip->bin_log_seqops.seqops =
&tpm2_binary_b_measurements_seqops;
else
chip->bin_log_seqops.seqops =
&tpm_binary_b_measurements_seqops;
chip->bios_dir[cnt] =
securityfs_create_file("binary_bios_measurements",
......@@ -418,8 +421,11 @@ int tpm_bios_log_setup(struct tpm_chip *chip)
goto err;
cnt++;
if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
chip->ascii_log_seqops.chip = chip;
chip->ascii_log_seqops.seqops = &tpm_ascii_b_measurements_seqops;
chip->ascii_log_seqops.seqops =
&tpm_ascii_b_measurements_seqops;
chip->bios_dir[cnt] =
securityfs_create_file("ascii_bios_measurements",
......@@ -429,6 +435,7 @@ int tpm_bios_log_setup(struct tpm_chip *chip)
if (IS_ERR(chip->bios_dir[cnt]))
goto err;
cnt++;
}
return 0;
......
This diff is collapsed.
/*
* Copyright (C) 2016 IBM Corporation
*
* Authors:
* Nayna Jain <nayna@linux.vnet.ibm.com>
*
* Access to TPM 2.0 event log as written by Firmware.
* It assumes that writer of event log has followed TCG Specification
* for Family "2.0" and written the event data in little endian.
* With that, it doesn't need any endian conversion for structure
* content.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/seq_file.h>
#include <linux/fs.h>
#include <linux/security.h>
#include <linux/module.h>
#include <linux/slab.h>
#include "tpm.h"
#include "tpm_eventlog.h"
/*
* calc_tpm2_event_size() - calculate the event size, where event
* is an entry in the TPM 2.0 event log. The event is of type Crypto
* Agile Log Entry Format as defined in TCG EFI Protocol Specification
* Family "2.0".
* @event: event whose size is to be calculated.
* @event_header: the first event in the event log.
*
* Returns size of the event. If it is an invalid event, returns 0.
*/
static int calc_tpm2_event_size(struct tcg_pcr_event2 *event,
struct tcg_pcr_event *event_header)
{
struct tcg_efi_specid_event *efispecid;
struct tcg_event_field *event_field;
void *marker;
void *marker_start;
u32 halg_size;
size_t size;
u16 halg;
int i;
int j;
marker = event;
marker_start = marker;
marker = marker + sizeof(event->pcr_idx) + sizeof(event->event_type)
+ sizeof(event->count);
efispecid = (struct tcg_efi_specid_event *)event_header->event;
for (i = 0; (i < event->count) && (i < TPM2_ACTIVE_PCR_BANKS);
i++) {
halg_size = sizeof(event->digests[i].alg_id);
memcpy(&halg, marker, halg_size);
marker = marker + halg_size;
for (j = 0; (j < efispecid->num_algs); j++) {
if (halg == efispecid->digest_sizes[j].alg_id) {
marker = marker +
efispecid->digest_sizes[j].digest_size;
break;
}
}
}
event_field = (struct tcg_event_field *)marker;
marker = marker + sizeof(event_field->event_size)
+ event_field->event_size;
size = marker - marker_start;
if ((event->event_type == 0) && (event_field->event_size == 0))
return 0;
return size;
}
static void *tpm2_bios_measurements_start(struct seq_file *m, loff_t *pos)
{
struct tpm_chip *chip = m->private;
struct tpm_bios_log *log = &chip->log;
void *addr = log->bios_event_log;
void *limit = log->bios_event_log_end;
struct tcg_pcr_event *event_header;
struct tcg_pcr_event2 *event;
size_t size;
int i;
event_header = addr;
size = sizeof(struct tcg_pcr_event) - sizeof(event_header->event)
+ event_header->event_size;
if (*pos == 0) {
if (addr + size < limit) {
if ((event_header->event_type == 0) &&
(event_header->event_size == 0))
return NULL;
return SEQ_START_TOKEN;
}
}
if (*pos > 0) {
addr += size;
event = addr;
size = calc_tpm2_event_size(event, event_header);
if ((addr + size >= limit) || (size == 0))
return NULL;
}
for (i = 0; i < (*pos - 1); i++) {
event = addr;
size = calc_tpm2_event_size(event, event_header);
if ((addr + size >= limit) || (size == 0))
return NULL;
addr += size;
}
return addr;
}
static void *tpm2_bios_measurements_next(struct seq_file *m, void *v,
loff_t *pos)
{
struct tcg_pcr_event *event_header;
struct tcg_pcr_event2 *event;
struct tpm_chip *chip = m->private;
struct tpm_bios_log *log = &chip->log;
void *limit = log->bios_event_log_end;
size_t event_size;
void *marker;
event_header = log->bios_event_log;
if (v == SEQ_START_TOKEN) {
event_size = sizeof(struct tcg_pcr_event) -
sizeof(event_header->event) + event_header->event_size;
marker = event_header;
} else {
event = v;
event_size = calc_tpm2_event_size(event, event_header);
if (event_size == 0)
return NULL;
marker = event;
}
marker = marker + event_size;
if (marker >= limit)
return NULL;
v = marker;
event = v;
event_size = calc_tpm2_event_size(event, event_header);
if (((v + event_size) >= limit) || (event_size == 0))
return NULL;
(*pos)++;
return v;
}
static void tpm2_bios_measurements_stop(struct seq_file *m, void *v)
{
}
static int tpm2_binary_bios_measurements_show(struct seq_file *m, void *v)
{
struct tpm_chip *chip = m->private;
struct tpm_bios_log *log = &chip->log;
struct tcg_pcr_event *event_header = log->bios_event_log;
struct tcg_pcr_event2 *event = v;
void *temp_ptr;
size_t size;
if (v == SEQ_START_TOKEN) {
size = sizeof(struct tcg_pcr_event) -
sizeof(event_header->event) + event_header->event_size;
temp_ptr = event_header;
if (size > 0)
seq_write(m, temp_ptr, size);
} else {
size = calc_tpm2_event_size(event, event_header);
temp_ptr = event;
if (size > 0)
seq_write(m, temp_ptr, size);
}
return 0;
}
const struct seq_operations tpm2_binary_b_measurements_seqops = {
.start = tpm2_bios_measurements_start,
.next = tpm2_bios_measurements_next,
.stop = tpm2_bios_measurements_stop,
.show = tpm2_binary_bios_measurements_show,
};
......@@ -54,6 +54,9 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
u64 len, start;
struct tpm_bios_log *log;
if (chip->flags & TPM_CHIP_FLAG_TPM2)
return -ENODEV;
log = &chip->log;
/* Unfortuntely ACPI does not associate the event log with a specific
......
......@@ -96,6 +96,12 @@ enum tpm_atmel_addr {
TPM_ATMEL_BASE_ADDR_HI = 0x09
};
static inline int tpm_read_index(int base, int index)
{
outb(index, base);
return inb(base+1) & 0xFF;
}
/* Verify this is a 1.1 Atmel TPM */
static int atmel_verify_tpm11(void)
{
......
......@@ -264,10 +264,12 @@ static const struct tpm_class_ops tpm_crb = {
static int crb_check_resource(struct acpi_resource *ares, void *data)
{
struct resource *io_res = data;
struct resource res;
struct resource_win win;
struct resource *res = &(win.res);
if (acpi_dev_resource_memory(ares, &res)) {
*io_res = res;
if (acpi_dev_resource_memory(ares, res) ||
acpi_dev_resource_address_space(ares, &win)) {
*io_res = *res;
io_res->name = NULL;
}
......
......@@ -2,9 +2,12 @@
#ifndef __TPM_EVENTLOG_H__
#define __TPM_EVENTLOG_H__
#include <crypto/hash_info.h>
#define TCG_EVENT_NAME_LEN_MAX 255
#define MAX_TEXT_EVENT 1000 /* Max event string length */
#define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */
#define TPM2_ACTIVE_PCR_BANKS 3
#ifdef CONFIG_PPC64
#define do_endian_conversion(x) be32_to_cpu(x)
......@@ -17,11 +20,6 @@ enum bios_platform_class {
BIOS_SERVER = 0x01,
};
struct tpm_bios_log {
void *bios_event_log;
void *bios_event_log_end;
};
struct tcpa_event {
u32 pcr_index;
u32 event_type;
......@@ -73,6 +71,49 @@ enum tcpa_pc_event_ids {
HOST_TABLE_OF_DEVICES,
};
/* http://www.trustedcomputinggroup.org/tcg-efi-protocol-specification/ */
struct tcg_efi_specid_event_algs {
u16 alg_id;
u16 digest_size;
} __packed;
struct tcg_efi_specid_event {
u8 signature[16];
u32 platform_class;
u8 spec_version_minor;
u8 spec_version_major;
u8 spec_errata;
u8 uintnsize;
u32 num_algs;
struct tcg_efi_specid_event_algs digest_sizes[TPM2_ACTIVE_PCR_BANKS];
u8 vendor_info_size;
u8 vendor_info[0];
} __packed;
struct tcg_pcr_event {
u32 pcr_idx;
u32 event_type;
u8 digest[20];
u32 event_size;
u8 event[0];
} __packed;
struct tcg_event_field {
u32 event_size;
u8 event[0];
} __packed;
struct tcg_pcr_event2 {
u32 pcr_idx;
u32 event_type;
u32 count;
struct tpm2_digest digests[TPM2_ACTIVE_PCR_BANKS];
struct tcg_event_field event;
} __packed;
extern const struct seq_operations tpm2_binary_b_measurements_seqops;
#if defined(CONFIG_ACPI)
int tpm_read_log_acpi(struct tpm_chip *chip);
#else
......
......@@ -40,11 +40,12 @@ MODULE_DEVICE_TABLE(vio, tpm_ibmvtpm_device_table);
/**
* ibmvtpm_send_crq - Send a CRQ request
*
* @vdev: vio device struct
* @w1: first word
* @w2: second word
*
* Return value:
* Return:
* 0 -Sucess
* Non-zero - Failure
*/
......@@ -55,11 +56,12 @@ static int ibmvtpm_send_crq(struct vio_dev *vdev, u64 w1, u64 w2)
/**
* tpm_ibmvtpm_recv - Receive data after send
*
* @chip: tpm chip struct
* @buf: buffer to read
* count: size of buffer
* @count: size of buffer
*
* Return value:
* Return:
* Number of bytes read
*/
static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
......@@ -96,12 +98,13 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
/**
* tpm_ibmvtpm_send - Send tpm request
*
* @chip: tpm chip struct
* @buf: buffer contains data to send
* count: size of buffer
* @count: size of buffer
*
* Return value:
* Number of bytes sent
* Return:
* Number of bytes sent or < 0 on error.
*/
static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
{
......@@ -170,11 +173,12 @@ static u8 tpm_ibmvtpm_status(struct tpm_chip *chip)
/**
* ibmvtpm_crq_get_rtce_size - Send a CRQ request to get rtce size
*
* @ibmvtpm: vtpm device struct
*
* Return value:
* 0 - Success
* Non-zero - Failure
* Return:
* 0 on success.
* Non-zero on failure.
*/
static int ibmvtpm_crq_get_rtce_size(struct ibmvtpm_dev *ibmvtpm)
{
......@@ -197,11 +201,12 @@ static int ibmvtpm_crq_get_rtce_size(struct ibmvtpm_dev *ibmvtpm)
/**
* ibmvtpm_crq_get_version - Send a CRQ request to get vtpm version
* - Note that this is vtpm version and not tpm version
*
* @ibmvtpm: vtpm device struct
*
* Return value:
* 0 - Success
* Non-zero - Failure
* Return:
* 0 on success.
* Non-zero on failure.
*/
static int ibmvtpm_crq_get_version(struct ibmvtpm_dev *ibmvtpm)
{
......@@ -225,9 +230,9 @@ static int ibmvtpm_crq_get_version(struct ibmvtpm_dev *ibmvtpm)
* ibmvtpm_crq_send_init_complete - Send a CRQ initialize complete message
* @ibmvtpm: vtpm device struct
*
* Return value:
* 0 - Success
* Non-zero - Failure
* Return:
* 0 on success.
* Non-zero on failure.
*/
static int ibmvtpm_crq_send_init_complete(struct ibmvtpm_dev *ibmvtpm)
{
......@@ -245,9 +250,9 @@ static int ibmvtpm_crq_send_init_complete(struct ibmvtpm_dev *ibmvtpm)
* ibmvtpm_crq_send_init - Send a CRQ initialize message
* @ibmvtpm: vtpm device struct
*
* Return value:
* 0 - Success
* Non-zero - Failure
* Return:
* 0 on success.
* Non-zero on failure.
*/
static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
{
......@@ -265,8 +270,7 @@ static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
* tpm_ibmvtpm_remove - ibm vtpm remove entry point
* @vdev: vio device struct
*
* Return value:
* 0
* Return: Always 0.
*/
static int tpm_ibmvtpm_remove(struct vio_dev *vdev)
{
......@@ -303,15 +307,16 @@ static int tpm_ibmvtpm_remove(struct vio_dev *vdev)
* tpm_ibmvtpm_get_desired_dma - Get DMA size needed by this driver
* @vdev: vio device struct
*
* Return value:
* Number of bytes the driver needs to DMA map
* Return:
* Number of bytes the driver needs to DMA map.
*/
static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev)
{
struct tpm_chip *chip = dev_get_drvdata(&vdev->dev);
struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
/* ibmvtpm initializes at probe time, so the data we are
/*
* ibmvtpm initializes at probe time, so the data we are
* asking for may not be set yet. Estimate that 4K required
* for TCE-mapped buffer in addition to CRQ.
*/
......@@ -325,8 +330,7 @@ static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev)
* tpm_ibmvtpm_suspend - Suspend
* @dev: device struct
*
* Return value:
* 0
* Return: Always 0.
*/
static int tpm_ibmvtpm_suspend(struct device *dev)
{
......@@ -350,11 +354,12 @@ static int tpm_ibmvtpm_suspend(struct device *dev)
/**
* ibmvtpm_reset_crq - Reset CRQ
*
* @ibmvtpm: ibm vtpm struct
*
* Return value:
* 0 - Success
* Non-zero - Failure
* Return:
* 0 on success.
* Non-zero on failure.
*/
static int ibmvtpm_reset_crq(struct ibmvtpm_dev *ibmvtpm)
{
......@@ -376,10 +381,10 @@ static int ibmvtpm_reset_crq(struct ibmvtpm_dev *ibmvtpm)
/**
* tpm_ibmvtpm_resume - Resume from suspend
*
* @dev: device struct
*
* Return value:
* 0
* Return: Always 0.
*/
static int tpm_ibmvtpm_resume(struct device *dev)
{
......@@ -434,10 +439,10 @@ static const struct dev_pm_ops tpm_ibmvtpm_pm_ops = {
/**
* ibmvtpm_crq_get_next - Get next responded crq
* @ibmvtpm vtpm device struct
*
* Return value:
* vtpm crq pointer
* @ibmvtpm: vtpm device struct
*
* Return: vtpm crq pointer or NULL.
*/
static struct ibmvtpm_crq *ibmvtpm_crq_get_next(struct ibmvtpm_dev *ibmvtpm)
{
......@@ -455,11 +460,10 @@ static struct ibmvtpm_crq *ibmvtpm_crq_get_next(struct ibmvtpm_dev *ibmvtpm)
/**
* ibmvtpm_crq_process - Process responded crq
* @crq crq to be processed
* @ibmvtpm vtpm device struct
*
* Return value:
* Nothing
* @crq: crq to be processed
* @ibmvtpm: vtpm device struct
*
*/
static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq,
struct ibmvtpm_dev *ibmvtpm)
......@@ -528,6 +532,7 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq,
/**
* ibmvtpm_interrupt - Interrupt handler
*
* @irq: irq number to handle
* @vtpm_instance: vtpm that received interrupt
*
......@@ -554,12 +559,13 @@ static irqreturn_t ibmvtpm_interrupt(int irq, void *vtpm_instance)
/**
* tpm_ibmvtpm_probe - ibm vtpm initialize entry point
*
* @vio_dev: vio device struct
* @id: vio device id struct
*
* Return value:
* 0 - Success
* Non-zero - Failure
* Return:
* 0 on success.
* Non-zero on failure.
*/
static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
const struct vio_device_id *id)
......@@ -671,11 +677,12 @@ static struct vio_driver ibmvtpm_driver = {
};
/**
* ibmvtpm_module_init - Initialize ibm vtpm module
* ibmvtpm_module_init - Initialize ibm vtpm module.
*
* Return value:
* 0 -Success
* Non-zero - Failure
*
* Return:
* 0 on success.
* Non-zero on failure.
*/
static int __init ibmvtpm_module_init(void)
{
......@@ -683,10 +690,7 @@ static int __init ibmvtpm_module_init(void)
}
/**
* ibmvtpm_module_exit - Teardown ibm vtpm module
*
* Return value:
* Nothing
* ibmvtpm_module_exit - Tear down ibm vtpm module.
*/
static void __exit ibmvtpm_module_exit(void)
{
......
......@@ -278,6 +278,18 @@ static struct platform_driver nsc_drv = {
},
};
static inline int tpm_read_index(int base, int index)
{
outb(index, base);
return inb(base+1) & 0xFF;
}
static inline void tpm_write_index(int base, int index, int value)
{
outb(index, base);
outb(value & 0xFF, base+1);
}
static int __init init_nsc(void)
{
int rc = 0;
......
......@@ -27,6 +27,8 @@ int tpm_read_log_of(struct tpm_chip *chip)
const u32 *sizep;
const u64 *basep;
struct tpm_bios_log *log;
u32 size;
u64 base;
log = &chip->log;
if (chip->dev.parent && chip->dev.parent->of_node)
......@@ -41,18 +43,35 @@ int tpm_read_log_of(struct tpm_chip *chip)
if (sizep == NULL || basep == NULL)
return -EIO;
if (*sizep == 0) {
/*
* For both vtpm/tpm, firmware has log addr and log size in big
* endian format. But in case of vtpm, there is a method called
* sml-handover which is run during kernel init even before
* device tree is setup. This sml-handover function takes care
* of endianness and writes to sml-base and sml-size in little
* endian format. For this reason, vtpm doesn't need conversion
* but physical tpm needs the conversion.
*/
if (of_property_match_string(np, "compatible", "IBM,vtpm") < 0) {
size = be32_to_cpup(sizep);
base = be64_to_cpup(basep);
} else {
size = *sizep;
base = *basep;
}
if (size == 0) {
dev_warn(&chip->dev, "%s: Event log area empty\n", __func__);
return -EIO;
}
log->bios_event_log = kmalloc(*sizep, GFP_KERNEL);
log->bios_event_log = kmalloc(size, GFP_KERNEL);
if (!log->bios_event_log)
return -ENOMEM;
log->bios_event_log_end = log->bios_event_log + *sizep;
log->bios_event_log_end = log->bios_event_log + size;
memcpy(log->bios_event_log, __va(*basep), *sizep);
memcpy(log->bios_event_log, __va(base), size);
return 0;
}
......@@ -159,7 +159,7 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
irq = tpm_info->irq;
if (itpm)
phy->priv.flags |= TPM_TIS_ITPM_POSSIBLE;
phy->priv.flags |= TPM_TIS_ITPM_WORKAROUND;
return tpm_tis_core_init(dev, &phy->priv, irq, &tpm_tcg,
acpi_dev_handle);
......@@ -432,7 +432,7 @@ static int __init init_tis(void)
acpi_bus_unregister_driver(&tis_acpi_driver);
err_acpi:
#endif
platform_device_unregister(force_pdev);
platform_driver_unregister(&tis_drv);
err_platform:
if (force_pdev)
platform_device_unregister(force_pdev);
......
......@@ -264,7 +264,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
int rc, status, burstcnt;
size_t count = 0;
bool itpm = priv->flags & TPM_TIS_ITPM_POSSIBLE;
bool itpm = priv->flags & TPM_TIS_ITPM_WORKAROUND;
if (request_locality(chip, 0) < 0)
return -EBUSY;
......@@ -464,6 +464,9 @@ static int probe_itpm(struct tpm_chip *chip)
size_t len = sizeof(cmd_getticks);
u16 vendor;
if (priv->flags & TPM_TIS_ITPM_WORKAROUND)
return 0;
rc = tpm_tis_read16(priv, TPM_DID_VID(0), &vendor);
if (rc < 0)
return rc;
......@@ -479,12 +482,15 @@ static int probe_itpm(struct tpm_chip *chip)
tpm_tis_ready(chip);
release_locality(chip, priv->locality, 0);
priv->flags |= TPM_TIS_ITPM_WORKAROUND;
rc = tpm_tis_send_data(chip, cmd_getticks, len);
if (rc == 0) {
if (rc == 0)
dev_info(&chip->dev, "Detected an iTPM.\n");
rc = 1;
} else
else {
priv->flags &= ~TPM_TIS_ITPM_WORKAROUND;
rc = -EFAULT;
}
out:
tpm_tis_ready(chip);
......@@ -552,7 +558,8 @@ static int tpm_tis_gen_interrupt(struct tpm_chip *chip)
if (chip->flags & TPM_CHIP_FLAG_TPM2)
return tpm2_get_tpm_pt(chip, 0x100, &cap2, desc);
else
return tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc);
return tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc,
0);
}
/* Register the IRQ and issue a command that will cause an interrupt. If an
......@@ -740,17 +747,12 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
(chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2",
vendor >> 16, rid);
if (!(priv->flags & TPM_TIS_ITPM_POSSIBLE)) {
probe = probe_itpm(chip);
if (probe < 0) {
rc = -ENODEV;
goto out_err;
}
if (!!probe)
priv->flags |= TPM_TIS_ITPM_POSSIBLE;
}
/* Figure out the capabilities */
rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps);
if (rc < 0)
......
......@@ -80,7 +80,7 @@ enum tis_defaults {
#define TPM_RID(l) (0x0F04 | ((l) << 12))
enum tpm_tis_flags {
TPM_TIS_ITPM_POSSIBLE = BIT(0),
TPM_TIS_ITPM_WORKAROUND = BIT(0),
};
struct tpm_tis_data {
......
......@@ -33,7 +33,6 @@
#include <linux/acpi.h>
#include <linux/freezer.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/gpio.h>
#include <linux/of_irq.h>
......
......@@ -65,7 +65,12 @@ static void vtpm_proxy_delete_device(struct proxy_dev *proxy_dev);
/**
* vtpm_proxy_fops_read - Read TPM commands on 'server side'
*
* Return value:
* @filp: file pointer
* @buf: read buffer
* @count: number of bytes to read
* @off: offset
*
* Return:
* Number of bytes read or negative error code
*/
static ssize_t vtpm_proxy_fops_read(struct file *filp, char __user *buf,
......@@ -115,7 +120,12 @@ static ssize_t vtpm_proxy_fops_read(struct file *filp, char __user *buf,
/**
* vtpm_proxy_fops_write - Write TPM responses on 'server side'
*
* Return value:
* @filp: file pointer
* @buf: write buffer
* @count: number of bytes to write
* @off: offset
*
* Return:
* Number of bytes read or negative error value
*/
static ssize_t vtpm_proxy_fops_write(struct file *filp, const char __user *buf,
......@@ -155,10 +165,12 @@ static ssize_t vtpm_proxy_fops_write(struct file *filp, const char __user *buf,
}
/*
* vtpm_proxy_fops_poll: Poll status on 'server side'
* vtpm_proxy_fops_poll - Poll status on 'server side'
*
* Return value:
* Poll flags
* @filp: file pointer
* @wait: poll table
*
* Return: Poll flags
*/
static unsigned int vtpm_proxy_fops_poll(struct file *filp, poll_table *wait)
{
......@@ -185,6 +197,8 @@ static unsigned int vtpm_proxy_fops_poll(struct file *filp, poll_table *wait)
/*
* vtpm_proxy_fops_open - Open vTPM device on 'server side'
*
* @filp: file pointer
*
* Called when setting up the anonymous file descriptor
*/
static void vtpm_proxy_fops_open(struct file *filp)
......@@ -196,8 +210,9 @@ static void vtpm_proxy_fops_open(struct file *filp)
/**
* vtpm_proxy_fops_undo_open - counter-part to vtpm_fops_open
*
* Call to undo vtpm_proxy_fops_open
*
*@proxy_dev: tpm proxy device
*/
static void vtpm_proxy_fops_undo_open(struct proxy_dev *proxy_dev)
{
......@@ -212,9 +227,11 @@ static void vtpm_proxy_fops_undo_open(struct proxy_dev *proxy_dev)
}
/*
* vtpm_proxy_fops_release: Close 'server side'
* vtpm_proxy_fops_release - Close 'server side'
*
* Return value:
* @inode: inode
* @filp: file pointer
* Return:
* Always returns 0.
*/
static int vtpm_proxy_fops_release(struct inode *inode, struct file *filp)
......@@ -245,7 +262,10 @@ static const struct file_operations vtpm_proxy_fops = {
/*
* Called when core TPM driver reads TPM responses from 'server side'
*
* Return value:
* @chip: tpm chip to use
* @buf: receive buffer
* @count: bytes to read
* Return:
* Number of TPM response bytes read, negative error value otherwise
*/
static int vtpm_proxy_tpm_op_recv(struct tpm_chip *chip, u8 *buf, size_t count)
......@@ -282,7 +302,11 @@ static int vtpm_proxy_tpm_op_recv(struct tpm_chip *chip, u8 *buf, size_t count)
/*
* Called when core TPM driver forwards TPM requests to 'server side'.
*
* Return value:
* @chip: tpm chip to use
* @buf: send buffer
* @count: bytes to send
*
* Return:
* 0 in case of success, negative error value otherwise.
*/
static int vtpm_proxy_tpm_op_send(struct tpm_chip *chip, u8 *buf, size_t count)
......@@ -442,7 +466,7 @@ static inline void vtpm_proxy_delete_proxy_dev(struct proxy_dev *proxy_dev)
/*
* Create a /dev/tpm%d and 'server side' file descriptor pair
*
* Return value:
* Return:
* Returns file pointer on success, an error value otherwise
*/
static struct file *vtpm_proxy_create_device(
......@@ -571,7 +595,7 @@ static long vtpmx_ioc_new_dev(struct file *file, unsigned int ioctl,
/*
* vtpmx_fops_ioctl: ioctl on /dev/vtpmx
*
* Return value:
* Return:
* Returns 0 on success, a negative error code otherwise.
*/
static long vtpmx_fops_ioctl(struct file *f, unsigned int ioctl,
......
......@@ -289,7 +289,6 @@ static int tpmfront_probe(struct xenbus_device *dev,
const struct xenbus_device_id *id)
{
struct tpm_private *priv;
struct tpm_chip *chip;
int rv;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
......@@ -306,7 +305,6 @@ static int tpmfront_probe(struct xenbus_device *dev,
rv = setup_ring(dev, priv);
if (rv) {
chip = dev_get_drvdata(&dev->dev);
ring_free(priv);
return rv;
}
......
......@@ -2488,6 +2488,12 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
length = -ESRCH;
if (!task)
goto out_no_task;
/* A task may only write its own attributes. */
length = -EACCES;
if (current != task)
goto out;
if (count > PAGE_SIZE)
count = PAGE_SIZE;
......@@ -2503,14 +2509,13 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
}
/* Guard against adverse ptrace interaction */
length = mutex_lock_interruptible(&task->signal->cred_guard_mutex);
length = mutex_lock_interruptible(&current->signal->cred_guard_mutex);
if (length < 0)
goto out_free;
length = security_setprocattr(task,
(char*)file->f_path.dentry->d_name.name,
length = security_setprocattr(file->f_path.dentry->d_name.name,
page, count);
mutex_unlock(&task->signal->cred_guard_mutex);
mutex_unlock(&current->signal->cred_guard_mutex);
out_free:
kfree(page);
out:
......
......@@ -352,8 +352,7 @@
* Return 0 if permission is granted.
* @inode_getattr:
* Check permission before obtaining file attributes.
* @mnt is the vfsmount where the dentry was looked up
* @dentry contains the dentry structure for the file.
* @path contains the path structure for the file.
* Return 0 if permission is granted.
* @inode_setxattr:
* Check permission before setting the extended attributes
......@@ -666,11 +665,6 @@
* @sig contains the signal value.
* @secid contains the sid of the process where the signal originated
* Return 0 if permission is granted.
* @task_wait:
* Check permission before allowing a process to reap a child process @p
* and collect its status information.
* @p contains the task_struct for process.
* Return 0 if permission is granted.
* @task_prctl:
* Check permission before performing a process control operation on the
* current process.
......@@ -1507,7 +1501,6 @@ union security_list_options {
int (*task_movememory)(struct task_struct *p);
int (*task_kill)(struct task_struct *p, struct siginfo *info,
int sig, u32 secid);
int (*task_wait)(struct task_struct *p);
int (*task_prctl)(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5);
void (*task_to_inode)(struct task_struct *p, struct inode *inode);
......@@ -1547,8 +1540,7 @@ union security_list_options {
void (*d_instantiate)(struct dentry *dentry, struct inode *inode);
int (*getprocattr)(struct task_struct *p, char *name, char **value);
int (*setprocattr)(struct task_struct *p, char *name, void *value,
size_t size);
int (*setprocattr)(const char *name, void *value, size_t size);
int (*ismaclabel)(const char *name);
int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen);
int (*secctx_to_secid)(const char *secdata, u32 seclen, u32 *secid);
......@@ -1768,7 +1760,6 @@ struct security_hook_heads {
struct list_head task_getscheduler;
struct list_head task_movememory;
struct list_head task_kill;
struct list_head task_wait;
struct list_head task_prctl;
struct list_head task_to_inode;
struct list_head ipc_permission;
......@@ -1876,6 +1867,7 @@ struct security_hook_list {
struct list_head list;
struct list_head *head;
union security_list_options hook;
char *lsm;
};
/*
......@@ -1888,15 +1880,10 @@ struct security_hook_list {
{ .head = &security_hook_heads.HEAD, .hook = { .HEAD = HOOK } }
extern struct security_hook_heads security_hook_heads;
extern char *lsm_names;
static inline void security_add_hooks(struct security_hook_list *hooks,
int count)
{
int i;
for (i = 0; i < count; i++)
list_add_tail_rcu(&hooks[i].list, hooks[i].head);
}
extern void security_add_hooks(struct security_hook_list *hooks, int count,
char *lsm);
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
/*
......
......@@ -332,7 +332,6 @@ int security_task_getscheduler(struct task_struct *p);
int security_task_movememory(struct task_struct *p);
int security_task_kill(struct task_struct *p, struct siginfo *info,
int sig, u32 secid);
int security_task_wait(struct task_struct *p);
int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5);
void security_task_to_inode(struct task_struct *p, struct inode *inode);
......@@ -361,7 +360,7 @@ int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
unsigned nsops, int alter);
void security_d_instantiate(struct dentry *dentry, struct inode *inode);
int security_getprocattr(struct task_struct *p, char *name, char **value);
int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size);
int security_setprocattr(const char *name, void *value, size_t size);
int security_netlink_send(struct sock *sk, struct sk_buff *skb);
int security_ismaclabel(const char *name);
int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
......@@ -980,11 +979,6 @@ static inline int security_task_kill(struct task_struct *p,
return 0;
}
static inline int security_task_wait(struct task_struct *p)
{
return 0;
}
static inline int security_task_prctl(int option, unsigned long arg2,
unsigned long arg3,
unsigned long arg4,
......@@ -1106,7 +1100,7 @@ static inline int security_getprocattr(struct task_struct *p, char *name, char *
return -EINVAL;
}
static inline int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size)
static inline int security_setprocattr(char *name, void *value, size_t size)
{
return -EINVAL;
}
......
......@@ -14,7 +14,6 @@
#include <linux/tty.h>
#include <linux/iocontext.h>
#include <linux/key.h>
#include <linux/security.h>
#include <linux/cpu.h>
#include <linux/acct.h>
#include <linux/tsacct_kern.h>
......@@ -1390,7 +1389,7 @@ static int wait_task_continued(struct wait_opts *wo, struct task_struct *p)
* Returns nonzero for a final return, when we have unlocked tasklist_lock.
* Returns zero if the search for a child should continue;
* then ->notask_error is 0 if @p is an eligible child,
* or another error from security_task_wait(), or still -ECHILD.
* or still -ECHILD.
*/
static int wait_consider_task(struct wait_opts *wo, int ptrace,
struct task_struct *p)
......@@ -1410,20 +1409,6 @@ static int wait_consider_task(struct wait_opts *wo, int ptrace,
if (!ret)
return ret;
ret = security_task_wait(p);
if (unlikely(ret < 0)) {
/*
* If we have not yet seen any eligible child,
* then let this error code replace -ECHILD.
* A permission error will give the user a clue
* to look for security policy problems, rather
* than for mysterious wait bugs.
*/
if (wo->notask_error)
wo->notask_error = ret;
return 0;
}
if (unlikely(exit_state == EXIT_TRACE)) {
/*
* ptrace == 0 means we are the natural parent. In this case
......@@ -1516,7 +1501,7 @@ static int wait_consider_task(struct wait_opts *wo, int ptrace,
* Returns nonzero for a final return, when we have unlocked tasklist_lock.
* Returns zero if the search for a child should continue; then
* ->notask_error is 0 if there were any eligible children,
* or another error from security_task_wait(), or still -ECHILD.
* or still -ECHILD.
*/
static int do_wait_thread(struct wait_opts *wo, struct task_struct *tsk)
{
......
......@@ -16,6 +16,7 @@
#include <linux/atomic.h>
#include <linux/audit.h>
#include <linux/compat.h>
#include <linux/coredump.h>
#include <linux/sched.h>
#include <linux/seccomp.h>
#include <linux/slab.h>
......@@ -486,6 +487,17 @@ void put_seccomp_filter(struct task_struct *tsk)
}
}
static void seccomp_init_siginfo(siginfo_t *info, int syscall, int reason)
{
memset(info, 0, sizeof(*info));
info->si_signo = SIGSYS;
info->si_code = SYS_SECCOMP;
info->si_call_addr = (void __user *)KSTK_EIP(current);
info->si_errno = reason;
info->si_arch = syscall_get_arch();
info->si_syscall = syscall;
}
/**
* seccomp_send_sigsys - signals the task to allow in-process syscall emulation
* @syscall: syscall number to send to userland
......@@ -496,13 +508,7 @@ void put_seccomp_filter(struct task_struct *tsk)
static void seccomp_send_sigsys(int syscall, int reason)
{
struct siginfo info;
memset(&info, 0, sizeof(info));
info.si_signo = SIGSYS;
info.si_code = SYS_SECCOMP;
info.si_call_addr = (void __user *)KSTK_EIP(current);
info.si_errno = reason;
info.si_arch = syscall_get_arch();
info.si_syscall = syscall;
seccomp_init_siginfo(&info, syscall, reason);
force_sig_info(SIGSYS, &info, current);
}
#endif /* CONFIG_SECCOMP_FILTER */
......@@ -634,10 +640,17 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
return 0;
case SECCOMP_RET_KILL:
default:
default: {
siginfo_t info;
audit_seccomp(this_syscall, SIGSYS, action);
/* Show the original registers in the dump. */
syscall_rollback(current, task_pt_regs(current));
/* Trigger a manual coredump since do_exit skips it. */
seccomp_init_siginfo(&info, this_syscall, data);
do_coredump(&info);
do_exit(SIGSYS);
}
}
unreachable();
......
......@@ -138,7 +138,7 @@ union arg64 {
#define ARG_32(idx) \
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx))
/* Loads hi into A and lo in X */
/* Loads lo into M[0] and hi into M[1] and A */
#define ARG_64(idx) \
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx)), \
BPF_STMT(BPF_ST, 0), /* lo -> M[0] */ \
......@@ -153,88 +153,107 @@ union arg64 {
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (value), 1, 0), \
jt
/* Checks the lo, then swaps to check the hi. A=lo,X=hi */
#define JA32(value, jt) \
BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (value), 0, 1), \
jt
#define JGE32(value, jt) \
BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 0, 1), \
jt
#define JGT32(value, jt) \
BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 0, 1), \
jt
#define JLE32(value, jt) \
BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 1, 0), \
jt
#define JLT32(value, jt) \
BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 1, 0), \
jt
/*
* All the JXX64 checks assume lo is saved in M[0] and hi is saved in both
* A and M[1]. This invariant is kept by restoring A if necessary.
*/
#define JEQ64(lo, hi, jt) \
/* if (hi != arg.hi) goto NOMATCH; */ \
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
/* if (lo != arg.lo) goto NOMATCH; */ \
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 0, 2), \
BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
BPF_STMT(BPF_LD+BPF_MEM, 1), \
jt, \
BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
BPF_STMT(BPF_LD+BPF_MEM, 1)
#define JNE64(lo, hi, jt) \
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 5, 0), \
BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
/* if (hi != arg.hi) goto MATCH; */ \
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 3), \
BPF_STMT(BPF_LD+BPF_MEM, 0), \
/* if (lo != arg.lo) goto MATCH; */ \
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 2, 0), \
BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
BPF_STMT(BPF_LD+BPF_MEM, 1), \
jt, \
BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
#define JA32(value, jt) \
BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (value), 0, 1), \
jt
BPF_STMT(BPF_LD+BPF_MEM, 1)
#define JA64(lo, hi, jt) \
/* if (hi & arg.hi) goto MATCH; */ \
BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (hi), 3, 0), \
BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
BPF_STMT(BPF_LD+BPF_MEM, 0), \
/* if (lo & arg.lo) goto MATCH; */ \
BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (lo), 0, 2), \
BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
BPF_STMT(BPF_LD+BPF_MEM, 1), \
jt, \
BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
BPF_STMT(BPF_LD+BPF_MEM, 1)
#define JGE32(value, jt) \
BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 0, 1), \
jt
#define JLT32(value, jt) \
BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 1, 0), \
jt
/* Shortcut checking if hi > arg.hi. */
#define JGE64(lo, hi, jt) \
/* if (hi > arg.hi) goto MATCH; */ \
BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \
/* if (hi != arg.hi) goto NOMATCH; */ \
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
BPF_STMT(BPF_LD+BPF_MEM, 0), \
/* if (lo >= arg.lo) goto MATCH; */ \
BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (lo), 0, 2), \
BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
jt, \
BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
#define JLT64(lo, hi, jt) \
BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 2, 0), \
BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
BPF_STMT(BPF_LD+BPF_MEM, 1), \
jt, \
BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
BPF_STMT(BPF_LD+BPF_MEM, 1)
#define JGT32(value, jt) \
BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 0, 1), \
jt
#define JLE32(value, jt) \
BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 1, 0), \
jt
/* Check hi > args.hi first, then do the GE checking */
#define JGT64(lo, hi, jt) \
/* if (hi > arg.hi) goto MATCH; */ \
BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \
/* if (hi != arg.hi) goto NOMATCH; */ \
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
BPF_STMT(BPF_LD+BPF_MEM, 0), \
/* if (lo > arg.lo) goto MATCH; */ \
BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 0, 2), \
BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
BPF_STMT(BPF_LD+BPF_MEM, 1), \
jt, \
BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
BPF_STMT(BPF_LD+BPF_MEM, 1)
#define JLE64(lo, hi, jt) \
BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 6, 0), \
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 3), \
BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
/* if (hi < arg.hi) goto MATCH; */ \
BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \
/* if (hi != arg.hi) goto NOMATCH; */ \
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
BPF_STMT(BPF_LD+BPF_MEM, 0), \
/* if (lo <= arg.lo) goto MATCH; */ \
BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 2, 0), \
BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
BPF_STMT(BPF_LD+BPF_MEM, 1), \
jt, \
BPF_STMT(BPF_LD+BPF_MEM, 1)
#define JLT64(lo, hi, jt) \
/* if (hi < arg.hi) goto MATCH; */ \
BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \
/* if (hi != arg.hi) goto NOMATCH; */ \
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
BPF_STMT(BPF_LD+BPF_MEM, 0), \
/* if (lo < arg.lo) goto MATCH; */ \
BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (lo), 2, 0), \
BPF_STMT(BPF_LD+BPF_MEM, 1), \
jt, \
BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
BPF_STMT(BPF_LD+BPF_MEM, 1)
#define LOAD_SYSCALL_NR \
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
......
......@@ -41,7 +41,9 @@
* signing with anything other than SHA1 - so we're stuck with that if such is
* the case.
*/
#if OPENSSL_VERSION_NUMBER < 0x10000000L || defined(OPENSSL_NO_CMS)
#if defined(LIBRESSL_VERSION_NUMBER) || \
OPENSSL_VERSION_NUMBER < 0x10000000L || \
defined(OPENSSL_NO_CMS)
#define USE_PKCS7
#endif
#ifndef USE_PKCS7
......
......@@ -36,7 +36,6 @@ config SECURITY_APPARMOR_HASH
select CRYPTO
select CRYPTO_SHA1
default y
help
This option selects whether introspection of loaded policy
is available to userspace via the apparmor filesystem.
......@@ -45,7 +44,6 @@ config SECURITY_APPARMOR_HASH_DEFAULT
bool "Enable policy hash introspection by default"
depends on SECURITY_APPARMOR_HASH
default y
help
This option selects whether sha1 hashing of loaded policy
is enabled by default. The generation of sha1 hashes for
......@@ -54,3 +52,32 @@ config SECURITY_APPARMOR_HASH_DEFAULT
however it can slow down policy load on some devices. In
these cases policy hashing can be disabled by default and
enabled only if needed.
config SECURITY_APPARMOR_DEBUG
bool "Build AppArmor with debug code"
depends on SECURITY_APPARMOR
default n
help
Build apparmor with debugging logic in apparmor. Not all
debugging logic will necessarily be enabled. A submenu will
provide fine grained control of the debug options that are
available.
config SECURITY_APPARMOR_DEBUG_ASSERTS
bool "Build AppArmor with debugging asserts"
depends on SECURITY_APPARMOR_DEBUG
default y
help
Enable code assertions made with AA_BUG. These are primarily
function entry preconditions but also exist at other key
points. If the assert is triggered it will trigger a WARN
message.
config SECURITY_APPARMOR_DEBUG_MESSAGES
bool "Debug messages enabled by default"
depends on SECURITY_APPARMOR_DEBUG
default n
help
Set the default value of the apparmor.debug kernel parameter.
When enabled, various debug messages will be logged to
the kernel message buffer.
......@@ -4,7 +4,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
resource.o sid.o file.o
resource.o secid.o file.o policy_ns.o
apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o
clean-files := capability_names.h rlim_names.h
......
This diff is collapsed.
......@@ -18,60 +18,8 @@
#include "include/apparmor.h"
#include "include/audit.h"
#include "include/policy.h"
#include "include/policy_ns.h"
const char *const op_table[] = {
"null",
"sysctl",
"capable",
"unlink",
"mkdir",
"rmdir",
"mknod",
"truncate",
"link",
"symlink",
"rename_src",
"rename_dest",
"chmod",
"chown",
"getattr",
"open",
"file_perm",
"file_lock",
"file_mmap",
"file_mprotect",
"create",
"post_create",
"bind",
"connect",
"listen",
"accept",
"sendmsg",
"recvmsg",
"getsockname",
"getpeername",
"getsockopt",
"setsockopt",
"socket_shutdown",
"ptrace",
"exec",
"change_hat",
"change_profile",
"change_onexec",
"setprocattr",
"setrlimit",
"profile_replace",
"profile_load",
"profile_remove"
};
const char *const audit_mode_names[] = {
"normal",
......@@ -114,23 +62,23 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
if (aa_g_audit_header) {
audit_log_format(ab, "apparmor=");
audit_log_string(ab, aa_audit_type[sa->aad->type]);
audit_log_string(ab, aa_audit_type[aad(sa)->type]);
}
if (sa->aad->op) {
if (aad(sa)->op) {
audit_log_format(ab, " operation=");
audit_log_string(ab, op_table[sa->aad->op]);
audit_log_string(ab, aad(sa)->op);
}
if (sa->aad->info) {
if (aad(sa)->info) {
audit_log_format(ab, " info=");
audit_log_string(ab, sa->aad->info);
if (sa->aad->error)
audit_log_format(ab, " error=%d", sa->aad->error);
audit_log_string(ab, aad(sa)->info);
if (aad(sa)->error)
audit_log_format(ab, " error=%d", aad(sa)->error);
}
if (sa->aad->profile) {
struct aa_profile *profile = sa->aad->profile;
if (aad(sa)->profile) {
struct aa_profile *profile = aad(sa)->profile;
if (profile->ns != root_ns) {
audit_log_format(ab, " namespace=");
audit_log_untrustedstring(ab, profile->ns->base.hname);
......@@ -139,9 +87,9 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
audit_log_untrustedstring(ab, profile->base.hname);
}
if (sa->aad->name) {
if (aad(sa)->name) {
audit_log_format(ab, " name=");
audit_log_untrustedstring(ab, sa->aad->name);
audit_log_untrustedstring(ab, aad(sa)->name);
}
}
......@@ -153,7 +101,7 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
void aa_audit_msg(int type, struct common_audit_data *sa,
void (*cb) (struct audit_buffer *, void *))
{
sa->aad->type = type;
aad(sa)->type = type;
common_lsm_audit(sa, audit_pre, cb);
}
......@@ -161,7 +109,6 @@ void aa_audit_msg(int type, struct common_audit_data *sa,
* aa_audit - Log a profile based audit event to the audit subsystem
* @type: audit type for the message
* @profile: profile to check against (NOT NULL)
* @gfp: allocation flags to use
* @sa: audit event (NOT NULL)
* @cb: optional callback fn for type specific fields (MAYBE NULL)
*
......@@ -169,14 +116,13 @@ void aa_audit_msg(int type, struct common_audit_data *sa,
*
* Returns: error on failure
*/
int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
struct common_audit_data *sa,
int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa,
void (*cb) (struct audit_buffer *, void *))
{
BUG_ON(!profile);
AA_BUG(!profile);
if (type == AUDIT_APPARMOR_AUTO) {
if (likely(!sa->aad->error)) {
if (likely(!aad(sa)->error)) {
if (AUDIT_MODE(profile) != AUDIT_ALL)
return 0;
type = AUDIT_APPARMOR_AUDIT;
......@@ -188,23 +134,23 @@ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
if (AUDIT_MODE(profile) == AUDIT_QUIET ||
(type == AUDIT_APPARMOR_DENIED &&
AUDIT_MODE(profile) == AUDIT_QUIET))
return sa->aad->error;
return aad(sa)->error;
if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED)
type = AUDIT_APPARMOR_KILL;
if (!unconfined(profile))
sa->aad->profile = profile;
aad(sa)->profile = profile;
aa_audit_msg(type, sa, cb);
if (sa->aad->type == AUDIT_APPARMOR_KILL)
if (aad(sa)->type == AUDIT_APPARMOR_KILL)
(void)send_sig_info(SIGKILL, NULL,
sa->type == LSM_AUDIT_DATA_TASK && sa->u.tsk ?
sa->u.tsk : current);
if (sa->aad->type == AUDIT_APPARMOR_ALLOWED)
return complain_error(sa->aad->error);
if (aad(sa)->type == AUDIT_APPARMOR_ALLOWED)
return complain_error(aad(sa)->error);
return sa->aad->error;
return aad(sa)->error;
}
......@@ -15,6 +15,7 @@
#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/gfp.h>
#include <linux/security.h>
#include "include/apparmor.h"
#include "include/capability.h"
......@@ -55,6 +56,7 @@ static void audit_cb(struct audit_buffer *ab, void *va)
* audit_caps - audit a capability
* @profile: profile being tested for confinement (NOT NULL)
* @cap: capability tested
@audit: whether an audit record should be generated
* @error: error code returned by test
*
* Do auditing of capability and handle, audit/complain/kill modes switching
......@@ -62,17 +64,16 @@ static void audit_cb(struct audit_buffer *ab, void *va)
*
* Returns: 0 or sa->error on success, error code on failure
*/
static int audit_caps(struct aa_profile *profile, int cap, int error)
static int audit_caps(struct aa_profile *profile, int cap, int audit,
int error)
{
struct audit_cache *ent;
int type = AUDIT_APPARMOR_AUTO;
struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
sa.type = LSM_AUDIT_DATA_CAP;
sa.aad = &aad;
DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_CAP, OP_CAPABLE);
sa.u.cap = cap;
sa.aad->op = OP_CAPABLE;
sa.aad->error = error;
aad(&sa)->error = error;
if (audit == SECURITY_CAP_NOAUDIT)
aad(&sa)->info = "optional: no audit";
if (likely(!error)) {
/* test if auditing is being forced */
......@@ -104,7 +105,7 @@ static int audit_caps(struct aa_profile *profile, int cap, int error)
}
put_cpu_var(audit_cache);
return aa_audit(type, profile, GFP_ATOMIC, &sa, audit_cb);
return aa_audit(type, profile, &sa, audit_cb);
}
/**
......@@ -133,11 +134,10 @@ int aa_capable(struct aa_profile *profile, int cap, int audit)
{
int error = profile_capable(profile, cap);
if (!audit) {
if (COMPLAIN_MODE(profile))
return complain_error(error);
if (audit == SECURITY_CAP_NOAUDIT) {
if (!COMPLAIN_MODE(profile))
return error;
}
return audit_caps(profile, cap, error);
return audit_caps(profile, cap, audit, error);
}
......@@ -13,11 +13,11 @@
* License.
*
*
* AppArmor sets confinement on every task, via the the aa_task_cxt and
* the aa_task_cxt.profile, both of which are required and are not allowed
* to be NULL. The aa_task_cxt is not reference counted and is unique
* AppArmor sets confinement on every task, via the the aa_task_ctx and
* the aa_task_ctx.profile, both of which are required and are not allowed
* to be NULL. The aa_task_ctx is not reference counted and is unique
* to each cred (which is reference count). The profile pointed to by
* the task_cxt is reference counted.
* the task_ctx is reference counted.
*
* TODO
* If a task uses change_hat it currently does not return to the old
......@@ -30,28 +30,28 @@
#include "include/policy.h"
/**
* aa_alloc_task_context - allocate a new task_cxt
* aa_alloc_task_context - allocate a new task_ctx
* @flags: gfp flags for allocation
*
* Returns: allocated buffer or NULL on failure
*/
struct aa_task_cxt *aa_alloc_task_context(gfp_t flags)
struct aa_task_ctx *aa_alloc_task_context(gfp_t flags)
{
return kzalloc(sizeof(struct aa_task_cxt), flags);
return kzalloc(sizeof(struct aa_task_ctx), flags);
}
/**
* aa_free_task_context - free a task_cxt
* @cxt: task_cxt to free (MAYBE NULL)
* aa_free_task_context - free a task_ctx
* @ctx: task_ctx to free (MAYBE NULL)
*/
void aa_free_task_context(struct aa_task_cxt *cxt)
void aa_free_task_context(struct aa_task_ctx *ctx)
{
if (cxt) {
aa_put_profile(cxt->profile);
aa_put_profile(cxt->previous);
aa_put_profile(cxt->onexec);
if (ctx) {
aa_put_profile(ctx->profile);
aa_put_profile(ctx->previous);
aa_put_profile(ctx->onexec);
kzfree(cxt);
kzfree(ctx);
}
}
......@@ -60,7 +60,7 @@ void aa_free_task_context(struct aa_task_cxt *cxt)
* @new: a blank task context (NOT NULL)
* @old: the task context to copy (NOT NULL)
*/
void aa_dup_task_context(struct aa_task_cxt *new, const struct aa_task_cxt *old)
void aa_dup_task_context(struct aa_task_ctx *new, const struct aa_task_ctx *old)
{
*new = *old;
aa_get_profile(new->profile);
......@@ -93,31 +93,36 @@ struct aa_profile *aa_get_task_profile(struct task_struct *task)
*/
int aa_replace_current_profile(struct aa_profile *profile)
{
struct aa_task_cxt *cxt = current_cxt();
struct aa_task_ctx *ctx = current_ctx();
struct cred *new;
BUG_ON(!profile);
AA_BUG(!profile);
if (cxt->profile == profile)
if (ctx->profile == profile)
return 0;
if (current_cred() != current_real_cred())
return -EBUSY;
new = prepare_creds();
if (!new)
return -ENOMEM;
cxt = cred_cxt(new);
if (unconfined(profile) || (cxt->profile->ns != profile->ns))
ctx = cred_ctx(new);
if (unconfined(profile) || (ctx->profile->ns != profile->ns))
/* if switching to unconfined or a different profile namespace
* clear out context state
*/
aa_clear_task_cxt_trans(cxt);
aa_clear_task_ctx_trans(ctx);
/* be careful switching cxt->profile, when racing replacement it
* is possible that cxt->profile->replacedby->profile is the reference
/*
* be careful switching ctx->profile, when racing replacement it
* is possible that ctx->profile->proxy->profile is the reference
* keeping @profile valid, so make sure to get its reference before
* dropping the reference on cxt->profile */
* dropping the reference on ctx->profile
*/
aa_get_profile(profile);
aa_put_profile(cxt->profile);
cxt->profile = profile;
aa_put_profile(ctx->profile);
ctx->profile = profile;
commit_creds(new);
return 0;
......@@ -131,15 +136,15 @@ int aa_replace_current_profile(struct aa_profile *profile)
*/
int aa_set_current_onexec(struct aa_profile *profile)
{
struct aa_task_cxt *cxt;
struct aa_task_ctx *ctx;
struct cred *new = prepare_creds();
if (!new)
return -ENOMEM;
cxt = cred_cxt(new);
ctx = cred_ctx(new);
aa_get_profile(profile);
aa_put_profile(cxt->onexec);
cxt->onexec = profile;
aa_put_profile(ctx->onexec);
ctx->onexec = profile;
commit_creds(new);
return 0;
......@@ -157,28 +162,28 @@ int aa_set_current_onexec(struct aa_profile *profile)
*/
int aa_set_current_hat(struct aa_profile *profile, u64 token)
{
struct aa_task_cxt *cxt;
struct aa_task_ctx *ctx;
struct cred *new = prepare_creds();
if (!new)
return -ENOMEM;
BUG_ON(!profile);
AA_BUG(!profile);
cxt = cred_cxt(new);
if (!cxt->previous) {
ctx = cred_ctx(new);
if (!ctx->previous) {
/* transfer refcount */
cxt->previous = cxt->profile;
cxt->token = token;
} else if (cxt->token == token) {
aa_put_profile(cxt->profile);
ctx->previous = ctx->profile;
ctx->token = token;
} else if (ctx->token == token) {
aa_put_profile(ctx->profile);
} else {
/* previous_profile && cxt->token != token */
/* previous_profile && ctx->token != token */
abort_creds(new);
return -EACCES;
}
cxt->profile = aa_get_newest_profile(profile);
ctx->profile = aa_get_newest_profile(profile);
/* clear exec on switching context */
aa_put_profile(cxt->onexec);
cxt->onexec = NULL;
aa_put_profile(ctx->onexec);
ctx->onexec = NULL;
commit_creds(new);
return 0;
......@@ -195,27 +200,27 @@ int aa_set_current_hat(struct aa_profile *profile, u64 token)
*/
int aa_restore_previous_profile(u64 token)
{
struct aa_task_cxt *cxt;
struct aa_task_ctx *ctx;
struct cred *new = prepare_creds();
if (!new)
return -ENOMEM;
cxt = cred_cxt(new);
if (cxt->token != token) {
ctx = cred_ctx(new);
if (ctx->token != token) {
abort_creds(new);
return -EACCES;
}
/* ignore restores when there is no saved profile */
if (!cxt->previous) {
if (!ctx->previous) {
abort_creds(new);
return 0;
}
aa_put_profile(cxt->profile);
cxt->profile = aa_get_newest_profile(cxt->previous);
BUG_ON(!cxt->profile);
aa_put_profile(ctx->profile);
ctx->profile = aa_get_newest_profile(ctx->previous);
AA_BUG(!ctx->profile);
/* clear exec && prev information when restoring to previous context */
aa_clear_task_cxt_trans(cxt);
aa_clear_task_ctx_trans(ctx);
commit_creds(new);
return 0;
......
......@@ -29,6 +29,43 @@ unsigned int aa_hash_size(void)
return apparmor_hash_size;
}
char *aa_calc_hash(void *data, size_t len)
{
struct {
struct shash_desc shash;
char ctx[crypto_shash_descsize(apparmor_tfm)];
} desc;
char *hash = NULL;
int error = -ENOMEM;
if (!apparmor_tfm)
return NULL;
hash = kzalloc(apparmor_hash_size, GFP_KERNEL);
if (!hash)
goto fail;
desc.shash.tfm = apparmor_tfm;
desc.shash.flags = 0;
error = crypto_shash_init(&desc.shash);
if (error)
goto fail;
error = crypto_shash_update(&desc.shash, (u8 *) data, len);
if (error)
goto fail;
error = crypto_shash_final(&desc.shash, hash);
if (error)
goto fail;
return hash;
fail:
kfree(hash);
return ERR_PTR(error);
}
int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start,
size_t len)
{
......@@ -37,7 +74,7 @@ int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start,
char ctx[crypto_shash_descsize(apparmor_tfm)];
} desc;
int error = -ENOMEM;
u32 le32_version = cpu_to_le32(version);
__le32 le32_version = cpu_to_le32(version);
if (!aa_g_hash_policy)
return 0;
......
This diff is collapsed.
......@@ -67,24 +67,24 @@ static void file_audit_cb(struct audit_buffer *ab, void *va)
struct common_audit_data *sa = va;
kuid_t fsuid = current_fsuid();
if (sa->aad->fs.request & AA_AUDIT_FILE_MASK) {
if (aad(sa)->fs.request & AA_AUDIT_FILE_MASK) {
audit_log_format(ab, " requested_mask=");
audit_file_mask(ab, sa->aad->fs.request);
audit_file_mask(ab, aad(sa)->fs.request);
}
if (sa->aad->fs.denied & AA_AUDIT_FILE_MASK) {
if (aad(sa)->fs.denied & AA_AUDIT_FILE_MASK) {
audit_log_format(ab, " denied_mask=");
audit_file_mask(ab, sa->aad->fs.denied);
audit_file_mask(ab, aad(sa)->fs.denied);
}
if (sa->aad->fs.request & AA_AUDIT_FILE_MASK) {
if (aad(sa)->fs.request & AA_AUDIT_FILE_MASK) {
audit_log_format(ab, " fsuid=%d",
from_kuid(&init_user_ns, fsuid));
audit_log_format(ab, " ouid=%d",
from_kuid(&init_user_ns, sa->aad->fs.ouid));
from_kuid(&init_user_ns, aad(sa)->fs.ouid));
}
if (sa->aad->fs.target) {
if (aad(sa)->fs.target) {
audit_log_format(ab, " target=");
audit_log_untrustedstring(ab, sa->aad->fs.target);
audit_log_untrustedstring(ab, aad(sa)->fs.target);
}
}
......@@ -104,54 +104,53 @@ static void file_audit_cb(struct audit_buffer *ab, void *va)
* Returns: %0 or error on failure
*/
int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
gfp_t gfp, int op, u32 request, const char *name,
const char *op, u32 request, const char *name,
const char *target, kuid_t ouid, const char *info, int error)
{
int type = AUDIT_APPARMOR_AUTO;
struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
sa.type = LSM_AUDIT_DATA_TASK;
DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_TASK, op);
sa.u.tsk = NULL;
aad(&sa)->fs.request = request;
aad(&sa)->name = name;
aad(&sa)->fs.target = target;
aad(&sa)->fs.ouid = ouid;
aad(&sa)->info = info;
aad(&sa)->error = error;
sa.u.tsk = NULL;
sa.aad = &aad;
aad.op = op,
aad.fs.request = request;
aad.name = name;
aad.fs.target = target;
aad.fs.ouid = ouid;
aad.info = info;
aad.error = error;
if (likely(!sa.aad->error)) {
if (likely(!aad(&sa)->error)) {
u32 mask = perms->audit;
if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
mask = 0xffff;
/* mask off perms that are not being force audited */
sa.aad->fs.request &= mask;
aad(&sa)->fs.request &= mask;
if (likely(!sa.aad->fs.request))
if (likely(!aad(&sa)->fs.request))
return 0;
type = AUDIT_APPARMOR_AUDIT;
} else {
/* only report permissions that were denied */
sa.aad->fs.request = sa.aad->fs.request & ~perms->allow;
aad(&sa)->fs.request = aad(&sa)->fs.request & ~perms->allow;
AA_BUG(!aad(&sa)->fs.request);
if (sa.aad->fs.request & perms->kill)
if (aad(&sa)->fs.request & perms->kill)
type = AUDIT_APPARMOR_KILL;
/* quiet known rejects, assumes quiet and kill do not overlap */
if ((sa.aad->fs.request & perms->quiet) &&
if ((aad(&sa)->fs.request & perms->quiet) &&
AUDIT_MODE(profile) != AUDIT_NOQUIET &&
AUDIT_MODE(profile) != AUDIT_ALL)
sa.aad->fs.request &= ~perms->quiet;
aad(&sa)->fs.request &= ~perms->quiet;
if (!sa.aad->fs.request)
return COMPLAIN_MODE(profile) ? 0 : sa.aad->error;
if (!aad(&sa)->fs.request)
return COMPLAIN_MODE(profile) ? 0 : aad(&sa)->error;
}
sa.aad->fs.denied = sa.aad->fs.request & ~perms->allow;
return aa_audit(type, profile, gfp, &sa, file_audit_cb);
aad(&sa)->fs.denied = aad(&sa)->fs.request & ~perms->allow;
return aa_audit(type, profile, &sa, file_audit_cb);
}
/**
......@@ -276,8 +275,9 @@ static inline bool is_deleted(struct dentry *dentry)
*
* Returns: %0 else error if access denied or other error
*/
int aa_path_perm(int op, struct aa_profile *profile, const struct path *path,
int flags, u32 request, struct path_cond *cond)
int aa_path_perm(const char *op, struct aa_profile *profile,
const struct path *path, int flags, u32 request,
struct path_cond *cond)
{
char *buffer = NULL;
struct file_perms perms = {};
......@@ -301,8 +301,8 @@ int aa_path_perm(int op, struct aa_profile *profile, const struct path *path,
if (request & ~perms.allow)
error = -EACCES;
}
error = aa_audit_file(profile, &perms, GFP_KERNEL, op, request, name,
NULL, cond->uid, info, error);
error = aa_audit_file(profile, &perms, op, request, name, NULL,
cond->uid, info, error);
kfree(buffer);
return error;
......@@ -349,8 +349,8 @@ static inline bool xindex_is_subset(u32 link, u32 target)
int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
const struct path *new_dir, struct dentry *new_dentry)
{
struct path link = { new_dir->mnt, new_dentry };
struct path target = { new_dir->mnt, old_dentry };
struct path link = { .mnt = new_dir->mnt, .dentry = new_dentry };
struct path target = { .mnt = new_dir->mnt, .dentry = old_dentry };
struct path_cond cond = {
d_backing_inode(old_dentry)->i_uid,
d_backing_inode(old_dentry)->i_mode
......@@ -429,7 +429,7 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
error = 0;
audit:
error = aa_audit_file(profile, &lperms, GFP_KERNEL, OP_LINK, request,
error = aa_audit_file(profile, &lperms, OP_LINK, request,
lname, tname, cond.uid, info, error);
kfree(buffer);
kfree(buffer2);
......@@ -446,7 +446,7 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
*
* Returns: %0 if access allowed else error
*/
int aa_file_perm(int op, struct aa_profile *profile, struct file *file,
int aa_file_perm(const char *op, struct aa_profile *profile, struct file *file,
u32 request)
{
struct path_cond cond = {
......
/*
* AppArmor security module
*
* This file contains AppArmor basic global and lib definitions
* This file contains AppArmor basic global
*
* Copyright (C) 1998-2008 Novell/SUSE
* Copyright 2009-2010 Canonical Ltd.
......@@ -15,10 +15,7 @@
#ifndef __APPARMOR_H
#define __APPARMOR_H
#include <linux/slab.h>
#include <linux/fs.h>
#include "match.h"
#include <linux/types.h>
/*
* Class of mediation types in the AppArmor policy db
......@@ -43,73 +40,4 @@ extern bool aa_g_logsyscall;
extern bool aa_g_paranoid_load;
extern unsigned int aa_g_path_max;
/*
* DEBUG remains global (no per profile flag) since it is mostly used in sysctl
* which is not related to profile accesses.
*/
#define AA_DEBUG(fmt, args...) \
do { \
if (aa_g_debug && printk_ratelimit()) \
printk(KERN_DEBUG "AppArmor: " fmt, ##args); \
} while (0)
#define AA_ERROR(fmt, args...) \
do { \
if (printk_ratelimit()) \
printk(KERN_ERR "AppArmor: " fmt, ##args); \
} while (0)
/* Flag indicating whether initialization completed */
extern int apparmor_initialized __initdata;
/* fn's in lib */
char *aa_split_fqname(char *args, char **ns_name);
void aa_info_message(const char *str);
void *__aa_kvmalloc(size_t size, gfp_t flags);
static inline void *kvmalloc(size_t size)
{
return __aa_kvmalloc(size, 0);
}
static inline void *kvzalloc(size_t size)
{
return __aa_kvmalloc(size, __GFP_ZERO);
}
/**
* aa_strneq - compare null terminated @str to a non null terminated substring
* @str: a null terminated string
* @sub: a substring, not necessarily null terminated
* @len: length of @sub to compare
*
* The @str string must be full consumed for this to be considered a match
*/
static inline bool aa_strneq(const char *str, const char *sub, int len)
{
return !strncmp(str, sub, len) && !str[len];
}
/**
* aa_dfa_null_transition - step to next state after null character
* @dfa: the dfa to match against
* @start: the state of the dfa to start matching in
*
* aa_dfa_null_transition transitions to the next state after a null
* character which is not used in standard matching and is only
* used to separate pairs.
*/
static inline unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
unsigned int start)
{
/* the null transition only needs the string's null terminator byte */
return aa_dfa_next(dfa, start, 0);
}
static inline bool mediated_filesystem(struct dentry *dentry)
{
return !(dentry->d_sb->s_flags & MS_NOUSER);
}
#endif /* __APPARMOR_H */
......@@ -15,6 +15,8 @@
#ifndef __AA_APPARMORFS_H
#define __AA_APPARMORFS_H
extern struct path aa_null;
enum aa_fs_type {
AA_FS_TYPE_BOOLEAN,
AA_FS_TYPE_STRING,
......@@ -62,12 +64,16 @@ extern const struct file_operations aa_fs_seq_file_ops;
extern void __init aa_destroy_aafs(void);
struct aa_profile;
struct aa_namespace;
struct aa_ns;
enum aafs_ns_type {
AAFS_NS_DIR,
AAFS_NS_PROFS,
AAFS_NS_NS,
AAFS_NS_RAW_DATA,
AAFS_NS_LOAD,
AAFS_NS_REPLACE,
AAFS_NS_REMOVE,
AAFS_NS_COUNT,
AAFS_NS_MAX_COUNT,
AAFS_NS_SIZE,
......@@ -83,12 +89,19 @@ enum aafs_prof_type {
AAFS_PROF_MODE,
AAFS_PROF_ATTACH,
AAFS_PROF_HASH,
AAFS_PROF_RAW_DATA,
AAFS_PROF_RAW_HASH,
AAFS_PROF_RAW_ABI,
AAFS_PROF_SIZEOF,
};
#define ns_dir(X) ((X)->dents[AAFS_NS_DIR])
#define ns_subns_dir(X) ((X)->dents[AAFS_NS_NS])
#define ns_subprofs_dir(X) ((X)->dents[AAFS_NS_PROFS])
#define ns_subdata_dir(X) ((X)->dents[AAFS_NS_RAW_DATA])
#define ns_subload(X) ((X)->dents[AAFS_NS_LOAD])
#define ns_subreplace(X) ((X)->dents[AAFS_NS_REPLACE])
#define ns_subremove(X) ((X)->dents[AAFS_NS_REMOVE])
#define prof_dir(X) ((X)->dents[AAFS_PROF_DIR])
#define prof_child_dir(X) ((X)->dents[AAFS_PROF_PROFS])
......@@ -97,8 +110,8 @@ void __aa_fs_profile_rmdir(struct aa_profile *profile);
void __aa_fs_profile_migrate_dents(struct aa_profile *old,
struct aa_profile *new);
int __aa_fs_profile_mkdir(struct aa_profile *profile, struct dentry *parent);
void __aa_fs_namespace_rmdir(struct aa_namespace *ns);
int __aa_fs_namespace_mkdir(struct aa_namespace *ns, struct dentry *parent,
void __aa_fs_ns_rmdir(struct aa_ns *ns);
int __aa_fs_ns_mkdir(struct aa_ns *ns, struct dentry *parent,
const char *name);
#endif /* __AA_APPARMORFS_H */
......@@ -46,79 +46,71 @@ enum audit_type {
AUDIT_APPARMOR_AUTO
};
extern const char *const op_table[];
enum aa_ops {
OP_NULL,
OP_SYSCTL,
OP_CAPABLE,
OP_UNLINK,
OP_MKDIR,
OP_RMDIR,
OP_MKNOD,
OP_TRUNC,
OP_LINK,
OP_SYMLINK,
OP_RENAME_SRC,
OP_RENAME_DEST,
OP_CHMOD,
OP_CHOWN,
OP_GETATTR,
OP_OPEN,
OP_FPERM,
OP_FLOCK,
OP_FMMAP,
OP_FMPROT,
OP_CREATE,
OP_POST_CREATE,
OP_BIND,
OP_CONNECT,
OP_LISTEN,
OP_ACCEPT,
OP_SENDMSG,
OP_RECVMSG,
OP_GETSOCKNAME,
OP_GETPEERNAME,
OP_GETSOCKOPT,
OP_SETSOCKOPT,
OP_SOCK_SHUTDOWN,
OP_PTRACE,
OP_EXEC,
OP_CHANGE_HAT,
OP_CHANGE_PROFILE,
OP_CHANGE_ONEXEC,
OP_SETPROCATTR,
OP_SETRLIMIT,
OP_PROF_REPL,
OP_PROF_LOAD,
OP_PROF_RM,
};
#define OP_NULL NULL
#define OP_SYSCTL "sysctl"
#define OP_CAPABLE "capable"
#define OP_UNLINK "unlink"
#define OP_MKDIR "mkdir"
#define OP_RMDIR "rmdir"
#define OP_MKNOD "mknod"
#define OP_TRUNC "truncate"
#define OP_LINK "link"
#define OP_SYMLINK "symlink"
#define OP_RENAME_SRC "rename_src"
#define OP_RENAME_DEST "rename_dest"
#define OP_CHMOD "chmod"
#define OP_CHOWN "chown"
#define OP_GETATTR "getattr"
#define OP_OPEN "open"
#define OP_FPERM "file_perm"
#define OP_FLOCK "file_lock"
#define OP_FMMAP "file_mmap"
#define OP_FMPROT "file_mprotect"
#define OP_CREATE "create"
#define OP_POST_CREATE "post_create"
#define OP_BIND "bind"
#define OP_CONNECT "connect"
#define OP_LISTEN "listen"
#define OP_ACCEPT "accept"
#define OP_SENDMSG "sendmsg"
#define OP_RECVMSG "recvmsg"
#define OP_GETSOCKNAME "getsockname"
#define OP_GETPEERNAME "getpeername"
#define OP_GETSOCKOPT "getsockopt"
#define OP_SETSOCKOPT "setsockopt"
#define OP_SHUTDOWN "socket_shutdown"
#define OP_PTRACE "ptrace"
#define OP_EXEC "exec"
#define OP_CHANGE_HAT "change_hat"
#define OP_CHANGE_PROFILE "change_profile"
#define OP_CHANGE_ONEXEC "change_onexec"
#define OP_SETPROCATTR "setprocattr"
#define OP_SETRLIMIT "setrlimit"
#define OP_PROF_REPL "profile_replace"
#define OP_PROF_LOAD "profile_load"
#define OP_PROF_RM "profile_remove"
struct apparmor_audit_data {
int error;
int op;
const char *op;
int type;
void *profile;
const char *name;
const char *info;
union {
void *target;
/* these entries require a custom callback fn */
struct {
long pos;
void *target;
} iface;
struct {
int rlim;
unsigned long max;
} rlim;
struct aa_profile *peer;
struct {
const char *target;
u32 request;
......@@ -126,17 +118,43 @@ struct apparmor_audit_data {
kuid_t ouid;
} fs;
};
struct {
const char *name;
long pos;
const char *ns;
} iface;
struct {
int rlim;
unsigned long max;
} rlim;
};
};
/* define a short hand for apparmor_audit_data structure */
#define aad apparmor_audit_data
/* macros for dealing with apparmor_audit_data structure */
#define aad(SA) ((SA)->apparmor_audit_data)
#define DEFINE_AUDIT_DATA(NAME, T, X) \
/* TODO: cleanup audit init so we don't need _aad = {0,} */ \
struct apparmor_audit_data NAME ## _aad = { .op = (X), }; \
struct common_audit_data NAME = \
{ \
.type = (T), \
.u.tsk = NULL, \
}; \
NAME.apparmor_audit_data = &(NAME ## _aad)
void aa_audit_msg(int type, struct common_audit_data *sa,
void (*cb) (struct audit_buffer *, void *));
int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
struct common_audit_data *sa,
int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa,
void (*cb) (struct audit_buffer *, void *));
#define aa_audit_error(ERROR, SA, CB) \
({ \
aad((SA))->error = (ERROR); \
aa_audit_msg(AUDIT_APPARMOR_ERROR, (SA), (CB)); \
aad((SA))->error; \
})
static inline int complain_error(int error)
{
if (error == -EPERM || error == -EACCES)
......
This diff is collapsed.
......@@ -18,9 +18,14 @@
#ifdef CONFIG_SECURITY_APPARMOR_HASH
unsigned int aa_hash_size(void);
char *aa_calc_hash(void *data, size_t len);
int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start,
size_t len);
#else
static inline char *aa_calc_hash(void *data, size_t len)
{
return NULL;
}
static inline int aa_calc_profile_hash(struct aa_profile *profile, u32 version,
void *start, size_t len)
{
......
......@@ -30,7 +30,7 @@ void apparmor_bprm_committed_creds(struct linux_binprm *bprm);
void aa_free_domain_entries(struct aa_domain *domain);
int aa_change_hat(const char *hats[], int count, u64 token, bool permtest);
int aa_change_profile(const char *ns_name, const char *name, bool onexec,
bool permtest);
int aa_change_profile(const char *fqname, bool onexec, bool permtest,
bool stack);
#endif /* __AA_DOMAIN_H */
......@@ -145,7 +145,7 @@ static inline u16 dfa_map_xindex(u16 mask)
dfa_map_xindex((ACCEPT_TABLE(dfa)[state] >> 14) & 0x3fff)
int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
gfp_t gfp, int op, u32 request, const char *name,
const char *op, u32 request, const char *name,
const char *target, kuid_t ouid, const char *info, int error);
/**
......@@ -171,13 +171,14 @@ unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start,
const char *name, struct path_cond *cond,
struct file_perms *perms);
int aa_path_perm(int op, struct aa_profile *profile, const struct path *path,
int flags, u32 request, struct path_cond *cond);
int aa_path_perm(const char *op, struct aa_profile *profile,
const struct path *path, int flags, u32 request,
struct path_cond *cond);
int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
const struct path *new_dir, struct dentry *new_dentry);
int aa_file_perm(int op, struct aa_profile *profile, struct file *file,
int aa_file_perm(const char *op, struct aa_profile *profile, struct file *file,
u32 request);
static inline void aa_free_file_rules(struct aa_file_rules *rules)
......
This diff is collapsed.
......@@ -100,13 +100,15 @@ struct aa_dfa {
struct table_header *tables[YYTD_ID_TSIZE];
};
extern struct aa_dfa *nulldfa;
#define byte_to_byte(X) (X)
#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \
#define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX) \
do { \
typeof(LEN) __i; \
TYPE *__t = (TYPE *) TABLE; \
TYPE *__b = (TYPE *) BLOB; \
TTYPE *__t = (TTYPE *) TABLE; \
BTYPE *__b = (BTYPE *) BLOB; \
for (__i = 0; __i < LEN; __i++) { \
__t[__i] = NTOHX(__b[__i]); \
} \
......@@ -117,6 +119,9 @@ static inline size_t table_size(size_t len, size_t el_size)
return ALIGN(sizeof(struct table_header) + len * el_size, 8);
}
int aa_setup_dfa_engine(void);
void aa_teardown_dfa_engine(void);
struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags);
unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
const char *str, int len);
......@@ -127,6 +132,21 @@ unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state,
void aa_dfa_free_kref(struct kref *kref);
/**
* aa_get_dfa - increment refcount on dfa @p
* @dfa: dfa (MAYBE NULL)
*
* Returns: pointer to @dfa if @dfa is NULL will return NULL
* Requires: @dfa must be held with valid refcount when called
*/
static inline struct aa_dfa *aa_get_dfa(struct aa_dfa *dfa)
{
if (dfa)
kref_get(&(dfa->count));
return dfa;
}
/**
* aa_put_dfa - put a dfa refcount
* @dfa: dfa to put refcount (MAYBE NULL)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
0x1B, 0x5E, 0x78, 0x3D, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x04, 0x90, 0x00, 0x00, 0x6E, 0x6F, 0x74, 0x66, 0x6C, 0x65, 0x78, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -1093,7 +1093,8 @@ struct security_hook_list capability_hooks[] = {
void __init capability_add_hooks(void)
{
security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks));
security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks),
"capability");
}
#endif /* CONFIG_SECURITY */
This diff is collapsed.
......@@ -204,7 +204,7 @@ int ima_store_template(struct ima_template_entry *entry, int violation,
struct inode *inode,
const unsigned char *filename, int pcr);
void ima_free_template_entry(struct ima_template_entry *entry);
const char *ima_d_path(const struct path *path, char **pathbuf);
const char *ima_d_path(const struct path *path, char **pathbuf, char *filename);
/* IMA policy related functions */
int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -182,7 +182,7 @@ static struct security_hook_list loadpin_hooks[] = {
void __init loadpin_add_hooks(void)
{
pr_info("ready to pin (currently %sabled)", enabled ? "en" : "dis");
security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks));
security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), "loadpin");
}
/* Should not be mutable after boot, so not listed in sysfs (perm == 0). */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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