Commit 83fdbfbf authored by Linus Torvalds's avatar Linus Torvalds

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

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6: (30 commits)
  TOMOYO: Add recursive directory matching operator support.
  remove CONFIG_SECURITY_FILE_CAPABILITIES compile option
  SELinux: print denials for buggy kernel with unknown perms
  Silence the existing API for capability version compatibility check.
  LSM: Move security_path_chmod()/security_path_chown() to after mutex_lock().
  SELinux: header generation may hit infinite loop
  selinux: Fix warnings
  security: report the module name to security_module_request
  Config option to set a default LSM
  sysctl: require CAP_SYS_RAWIO to set mmap_min_addr
  tpm: autoload tpm_tis based on system PnP IDs
  tpm_tis: TPM_STS_DATA_EXPECT workaround
  define convenient securebits masks for prctl users (v2)
  tpm: fix header for modular build
  tomoyo: improve hash bucket dispersion
  tpm add default function definitions
  LSM: imbed ima calls in the security hooks
  SELinux: add .gitignore files for dynamic classes
  security: remove root_plug
  SELinux: fix locking issue introduced with c6d3aaa4
  ...
parents d9b2c4d0 c84d6efd
......@@ -65,6 +65,7 @@ aicdb.h*
asm-offsets.h
asm_offsets.h
autoconf.h*
av_permissions.h
bbootsect
bin2c
binkernel.spec
......@@ -95,12 +96,14 @@ docproc
elf2ecoff
elfconfig.h*
fixdep
flask.h
fore200e_mkfirm
fore200e_pca_fw.c*
gconf
gen-devlist
gen_crc32table
gen_init_cpio
genheaders
genksyms
*_gray256.c
ihex2fw
......
......@@ -85,7 +85,6 @@ parameter is applicable:
PPT Parallel port support is enabled.
PS2 Appropriate PS/2 support is enabled.
RAM RAM disk support is enabled.
ROOTPLUG The example Root Plug LSM is enabled.
S390 S390 architecture is enabled.
SCSI Appropriate SCSI support is enabled.
A lot of drivers has their options described inside of
......@@ -2164,15 +2163,6 @@ and is between 256 and 4096 characters. It is defined in the file
Useful for devices that are detected asynchronously
(e.g. USB and MMC devices).
root_plug.vendor_id=
[ROOTPLUG] Override the default vendor ID
root_plug.product_id=
[ROOTPLUG] Override the default product ID
root_plug.debug=
[ROOTPLUG] Enable debugging output
rw [KNL] Mount root device read-write on boot
S [KNL] Run init in single mode
......
......@@ -31,7 +31,7 @@
enum tpm_const {
TPM_MINOR = 224, /* officially assigned */
TPM_BUFSIZE = 2048,
TPM_BUFSIZE = 4096,
TPM_NUM_DEVICES = 256,
};
......
......@@ -257,6 +257,10 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
return size;
}
static int itpm;
module_param(itpm, bool, 0444);
MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)");
/*
* If interrupts are used (signaled by an irq set in the vendor structure)
* tpm.c can skip polling for the data to be available as the interrupt is
......@@ -293,7 +297,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
&chip->vendor.int_queue);
status = tpm_tis_status(chip);
if ((status & TPM_STS_DATA_EXPECT) == 0) {
if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) {
rc = -EIO;
goto out_err;
}
......@@ -467,6 +471,10 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
"1.2 TPM (device-id 0x%X, rev-id %d)\n",
vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
if (itpm)
dev_info(dev, "Intel iTPM workaround enabled\n");
/* Figure out the capabilities */
intfcaps =
ioread32(chip->vendor.iobase +
......@@ -629,6 +637,7 @@ static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
{"", 0}, /* User Specified */
{"", 0} /* Terminator */
};
MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl);
static __devexit void tpm_tis_pnp_remove(struct pnp_dev *dev)
{
......
......@@ -46,7 +46,6 @@
#include <linux/proc_fs.h>
#include <linux/mount.h>
#include <linux/security.h>
#include <linux/ima.h>
#include <linux/syscalls.h>
#include <linux/tsacct_kern.h>
#include <linux/cn_proc.h>
......@@ -1207,9 +1206,6 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
struct linux_binfmt *fmt;
retval = security_bprm_check(bprm);
if (retval)
return retval;
retval = ima_bprm_check(bprm);
if (retval)
return retval;
......
......@@ -13,7 +13,6 @@
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/security.h>
#include <linux/ima.h>
#include <linux/eventpoll.h>
#include <linux/rcupdate.h>
#include <linux/mount.h>
......@@ -280,7 +279,6 @@ void __fput(struct file *file)
if (file->f_op && file->f_op->release)
file->f_op->release(inode, file);
security_file_free(file);
ima_file_free(file);
if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL))
cdev_put(inode->i_cdev);
fops_put(file->f_op);
......
......@@ -18,7 +18,6 @@
#include <linux/hash.h>
#include <linux/swap.h>
#include <linux/security.h>
#include <linux/ima.h>
#include <linux/pagemap.h>
#include <linux/cdev.h>
#include <linux/bootmem.h>
......@@ -157,11 +156,6 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
if (security_inode_alloc(inode))
goto out;
/* allocate and initialize an i_integrity */
if (ima_inode_alloc(inode))
goto out_free_security;
spin_lock_init(&inode->i_lock);
lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key);
......@@ -201,9 +195,6 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
#endif
return 0;
out_free_security:
security_inode_free(inode);
out:
return -ENOMEM;
}
......@@ -235,7 +226,6 @@ static struct inode *alloc_inode(struct super_block *sb)
void __destroy_inode(struct inode *inode)
{
BUG_ON(inode_has_buffers(inode));
ima_inode_free(inode);
security_inode_free(inode);
fsnotify_inode_delete(inode);
#ifdef CONFIG_FS_POSIX_ACL
......
......@@ -1921,6 +1921,16 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
if (data_page)
((char *)data_page)[PAGE_SIZE - 1] = 0;
/* ... and get the mountpoint */
retval = kern_path(dir_name, LOOKUP_FOLLOW, &path);
if (retval)
return retval;
retval = security_sb_mount(dev_name, &path,
type_page, flags, data_page);
if (retval)
goto dput_out;
/* Default to relatime unless overriden */
if (!(flags & MS_NOATIME))
mnt_flags |= MNT_RELATIME;
......@@ -1945,16 +1955,6 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
MS_STRICTATIME);
/* ... and get the mountpoint */
retval = kern_path(dir_name, LOOKUP_FOLLOW, &path);
if (retval)
return retval;
retval = security_sb_mount(dev_name, &path,
type_page, flags, data_page);
if (retval)
goto dput_out;
if (flags & MS_REMOUNT)
retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,
data_page);
......
......@@ -587,6 +587,9 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename)
error = -EPERM;
if (!capable(CAP_SYS_CHROOT))
goto dput_and_out;
error = security_path_chroot(&path);
if (error)
goto dput_and_out;
set_fs_root(current->fs, &path);
error = 0;
......@@ -617,11 +620,15 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode)
if (err)
goto out_putf;
mutex_lock(&inode->i_mutex);
err = security_path_chmod(dentry, file->f_vfsmnt, mode);
if (err)
goto out_unlock;
if (mode == (mode_t) -1)
mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
err = notify_change(dentry, &newattrs);
out_unlock:
mutex_unlock(&inode->i_mutex);
mnt_drop_write(file->f_path.mnt);
out_putf:
......@@ -646,11 +653,15 @@ SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode)
if (error)
goto dput_and_out;
mutex_lock(&inode->i_mutex);
error = security_path_chmod(path.dentry, path.mnt, mode);
if (error)
goto out_unlock;
if (mode == (mode_t) -1)
mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
error = notify_change(path.dentry, &newattrs);
out_unlock:
mutex_unlock(&inode->i_mutex);
mnt_drop_write(path.mnt);
dput_and_out:
......@@ -664,9 +675,9 @@ SYSCALL_DEFINE2(chmod, const char __user *, filename, mode_t, mode)
return sys_fchmodat(AT_FDCWD, filename, mode);
}
static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
static int chown_common(struct path *path, uid_t user, gid_t group)
{
struct inode *inode = dentry->d_inode;
struct inode *inode = path->dentry->d_inode;
int error;
struct iattr newattrs;
......@@ -683,7 +694,9 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
newattrs.ia_valid |=
ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
mutex_lock(&inode->i_mutex);
error = notify_change(dentry, &newattrs);
error = security_path_chown(path, user, group);
if (!error)
error = notify_change(path->dentry, &newattrs);
mutex_unlock(&inode->i_mutex);
return error;
......@@ -700,7 +713,7 @@ SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group)
error = mnt_want_write(path.mnt);
if (error)
goto out_release;
error = chown_common(path.dentry, user, group);
error = chown_common(&path, user, group);
mnt_drop_write(path.mnt);
out_release:
path_put(&path);
......@@ -725,7 +738,7 @@ SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user,
error = mnt_want_write(path.mnt);
if (error)
goto out_release;
error = chown_common(path.dentry, user, group);
error = chown_common(&path, user, group);
mnt_drop_write(path.mnt);
out_release:
path_put(&path);
......@@ -744,7 +757,7 @@ SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group
error = mnt_want_write(path.mnt);
if (error)
goto out_release;
error = chown_common(path.dentry, user, group);
error = chown_common(&path, user, group);
mnt_drop_write(path.mnt);
out_release:
path_put(&path);
......@@ -767,7 +780,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
goto out_fput;
dentry = file->f_path.dentry;
audit_inode(NULL, dentry);
error = chown_common(dentry, user, group);
error = chown_common(&file->f_path, user, group);
mnt_drop_write(file->f_path.mnt);
out_fput:
fput(file);
......
......@@ -330,6 +330,7 @@ unifdef-y += scc.h
unifdef-y += sched.h
unifdef-y += screen_info.h
unifdef-y += sdla.h
unifdef-y += securebits.h
unifdef-y += selinux_netlink.h
unifdef-y += sem.h
unifdef-y += serial_core.h
......
......@@ -92,9 +92,7 @@ struct vfs_cap_data {
#define _KERNEL_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_3
#define _KERNEL_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_3
#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
extern int file_caps_enabled;
#endif
typedef struct kernel_cap_struct {
__u32 cap[_KERNEL_CAPABILITY_U32S];
......
......@@ -83,16 +83,12 @@ extern struct group_info init_groups;
#define INIT_IDS
#endif
#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
/*
* Because of the reduced scope of CAP_SETPCAP when filesystem
* capabilities are in effect, it is safe to allow CAP_SETPCAP to
* be available in the default configuration.
*/
# define CAP_INIT_BSET CAP_FULL_SET
#else
# define CAP_INIT_BSET CAP_INIT_EFF_SET
#endif
#ifdef CONFIG_TREE_PREEMPT_RCU
#define INIT_TASK_RCU_PREEMPT(tsk) \
......
......@@ -34,6 +34,7 @@ struct common_audit_data {
#define LSM_AUDIT_DATA_TASK 5
#define LSM_AUDIT_DATA_KEY 6
#define LSM_AUDIT_NO_AUDIT 7
#define LSM_AUDIT_DATA_KMOD 8
struct task_struct *tsk;
union {
struct {
......@@ -66,6 +67,7 @@ struct common_audit_data {
char *key_desc;
} key_struct;
#endif
char *kmod_name;
} u;
/* this union contains LSM specific data */
union {
......
#ifndef _LINUX_SECUREBITS_H
#define _LINUX_SECUREBITS_H 1
/* Each securesetting is implemented using two bits. One bit specifies
whether the setting is on or off. The other bit specify whether the
setting is locked or not. A setting which is locked cannot be
changed from user-level. */
#define issecure_mask(X) (1 << (X))
#ifdef __KERNEL__
#define issecure(X) (issecure_mask(X) & current_cred_xxx(securebits))
#endif
#define SECUREBITS_DEFAULT 0x00000000
/* When set UID 0 has no special privileges. When unset, we support
......@@ -12,6 +21,9 @@
#define SECURE_NOROOT 0
#define SECURE_NOROOT_LOCKED 1 /* make bit-0 immutable */
#define SECBIT_NOROOT (issecure_mask(SECURE_NOROOT))
#define SECBIT_NOROOT_LOCKED (issecure_mask(SECURE_NOROOT_LOCKED))
/* When set, setuid to/from uid 0 does not trigger capability-"fixup".
When unset, to provide compatiblility with old programs relying on
set*uid to gain/lose privilege, transitions to/from uid 0 cause
......@@ -19,6 +31,10 @@
#define SECURE_NO_SETUID_FIXUP 2
#define SECURE_NO_SETUID_FIXUP_LOCKED 3 /* make bit-2 immutable */
#define SECBIT_NO_SETUID_FIXUP (issecure_mask(SECURE_NO_SETUID_FIXUP))
#define SECBIT_NO_SETUID_FIXUP_LOCKED \
(issecure_mask(SECURE_NO_SETUID_FIXUP_LOCKED))
/* When set, a process can retain its capabilities even after
transitioning to a non-root user (the set-uid fixup suppressed by
bit 2). Bit-4 is cleared when a process calls exec(); setting both
......@@ -27,12 +43,8 @@
#define SECURE_KEEP_CAPS 4
#define SECURE_KEEP_CAPS_LOCKED 5 /* make bit-4 immutable */
/* Each securesetting is implemented using two bits. One bit specifies
whether the setting is on or off. The other bit specify whether the
setting is locked or not. A setting which is locked cannot be
changed from user-level. */
#define issecure_mask(X) (1 << (X))
#define issecure(X) (issecure_mask(X) & current_cred_xxx(securebits))
#define SECBIT_KEEP_CAPS (issecure_mask(SECURE_KEEP_CAPS))
#define SECBIT_KEEP_CAPS_LOCKED (issecure_mask(SECURE_KEEP_CAPS_LOCKED))
#define SECURE_ALL_BITS (issecure_mask(SECURE_NOROOT) | \
issecure_mask(SECURE_NO_SETUID_FIXUP) | \
......
......@@ -447,6 +447,22 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* @new_dir contains the path structure for parent of the new link.
* @new_dentry contains the dentry structure of the new link.
* Return 0 if permission is granted.
* @path_chmod:
* Check for permission to change DAC's permission of a file or directory.
* @dentry contains the dentry structure.
* @mnt contains the vfsmnt structure.
* @mode contains DAC's mode.
* Return 0 if permission is granted.
* @path_chown:
* Check for permission to change owner/group of a file or directory.
* @path contains the path structure.
* @uid contains new owner's ID.
* @gid contains new group's ID.
* Return 0 if permission is granted.
* @path_chroot:
* Check for permission to change root directory.
* @path contains the path structure.
* Return 0 if permission is granted.
* @inode_readlink:
* Check the permission to read the symbolic link.
* @dentry contains the dentry structure for the file link.
......@@ -690,6 +706,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* @kernel_module_request:
* Ability to trigger the kernel to automatically upcall to userspace for
* userspace to load a kernel module with the given name.
* @kmod_name name of the module requested by the kernel
* Return 0 if successful.
* @task_setuid:
* Check permission before setting one or more of the user identity
......@@ -1488,6 +1505,10 @@ struct security_operations {
struct dentry *new_dentry);
int (*path_rename) (struct path *old_dir, struct dentry *old_dentry,
struct path *new_dir, struct dentry *new_dentry);
int (*path_chmod) (struct dentry *dentry, struct vfsmount *mnt,
mode_t mode);
int (*path_chown) (struct path *path, uid_t uid, gid_t gid);
int (*path_chroot) (struct path *path);
#endif
int (*inode_alloc_security) (struct inode *inode);
......@@ -1557,7 +1578,7 @@ struct security_operations {
void (*cred_transfer)(struct cred *new, const struct cred *old);
int (*kernel_act_as)(struct cred *new, u32 secid);
int (*kernel_create_files_as)(struct cred *new, struct inode *inode);
int (*kernel_module_request)(void);
int (*kernel_module_request)(char *kmod_name);
int (*task_setuid) (uid_t id0, uid_t id1, uid_t id2, int flags);
int (*task_fix_setuid) (struct cred *new, const struct cred *old,
int flags);
......@@ -1822,7 +1843,7 @@ void security_commit_creds(struct cred *new, const struct cred *old);
void security_transfer_creds(struct cred *new, const struct cred *old);
int security_kernel_act_as(struct cred *new, u32 secid);
int security_kernel_create_files_as(struct cred *new, struct inode *inode);
int security_kernel_module_request(void);
int security_kernel_module_request(char *kmod_name);
int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags);
int security_task_fix_setuid(struct cred *new, const struct cred *old,
int flags);
......@@ -2387,7 +2408,7 @@ static inline int security_kernel_create_files_as(struct cred *cred,
return 0;
}
static inline int security_kernel_module_request(void)
static inline int security_kernel_module_request(char *kmod_name)
{
return 0;
}
......@@ -2952,6 +2973,10 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
struct dentry *new_dentry);
int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
struct path *new_dir, struct dentry *new_dentry);
int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
mode_t mode);
int security_path_chown(struct path *path, uid_t uid, gid_t gid);
int security_path_chroot(struct path *path);
#else /* CONFIG_SECURITY_PATH */
static inline int security_path_unlink(struct path *dir, struct dentry *dentry)
{
......@@ -3001,6 +3026,23 @@ static inline int security_path_rename(struct path *old_dir,
{
return 0;
}
static inline int security_path_chmod(struct dentry *dentry,
struct vfsmount *mnt,
mode_t mode)
{
return 0;
}
static inline int security_path_chown(struct path *path, uid_t uid, gid_t gid)
{
return 0;
}
static inline int security_path_chroot(struct path *path)
{
return 0;
}
#endif /* CONFIG_SECURITY_PATH */
#ifdef CONFIG_KEYS
......
......@@ -27,9 +27,16 @@
*/
#define TPM_ANY_NUM 0xFFFF
#if defined(CONFIG_TCG_TPM)
#if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE)
extern int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf);
extern int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash);
#else
static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) {
return -ENODEV;
}
static inline int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) {
return -ENODEV;
}
#endif
#endif
......@@ -29,7 +29,6 @@ EXPORT_SYMBOL(__cap_empty_set);
EXPORT_SYMBOL(__cap_full_set);
EXPORT_SYMBOL(__cap_init_eff_set);
#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
int file_caps_enabled = 1;
static int __init file_caps_disable(char *str)
......@@ -38,7 +37,6 @@ static int __init file_caps_disable(char *str)
return 1;
}
__setup("no_file_caps", file_caps_disable);
#endif
/*
* More recent versions of libcap are available from:
......@@ -169,8 +167,8 @@ SYSCALL_DEFINE2(capget, cap_user_header_t, header, cap_user_data_t, dataptr)
kernel_cap_t pE, pI, pP;
ret = cap_validate_magic(header, &tocopy);
if (ret != 0)
return ret;
if ((dataptr == NULL) || (ret != 0))
return ((dataptr == NULL) && (ret == -EINVAL)) ? 0 : ret;
if (get_user(pid, &header->pid))
return -EFAULT;
......@@ -238,7 +236,7 @@ SYSCALL_DEFINE2(capget, cap_user_header_t, header, cap_user_data_t, dataptr)
SYSCALL_DEFINE2(capset, cap_user_header_t, header, const cap_user_data_t, data)
{
struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S];
unsigned i, tocopy;
unsigned i, tocopy, copybytes;
kernel_cap_t inheritable, permitted, effective;
struct cred *new;
int ret;
......@@ -255,8 +253,11 @@ SYSCALL_DEFINE2(capset, cap_user_header_t, header, const cap_user_data_t, data)
if (pid != 0 && pid != task_pid_vnr(current))
return -EPERM;
if (copy_from_user(&kdata, data,
tocopy * sizeof(struct __user_cap_data_struct)))
copybytes = tocopy * sizeof(struct __user_cap_data_struct);
if (copybytes > sizeof(kdata))
return -EFAULT;
if (copy_from_user(&kdata, data, copybytes))
return -EFAULT;
for (i = 0; i < tocopy; i++) {
......
......@@ -80,16 +80,16 @@ int __request_module(bool wait, const char *fmt, ...)
#define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */
static int kmod_loop_msg;
ret = security_kernel_module_request();
if (ret)
return ret;
va_start(args, fmt);
ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);
va_end(args);
if (ret >= MODULE_NAME_LEN)
return -ENAMETOOLONG;
ret = security_kernel_module_request(module_name);
if (ret)
return ret;
/* If modprobe needs a service that is in a module, we get a recursive
* loop. Limit the number of running kmod threads to max_threads/2 or
* MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method
......
......@@ -20,7 +20,6 @@
#include <linux/fs.h>
#include <linux/personality.h>
#include <linux/security.h>
#include <linux/ima.h>
#include <linux/hugetlb.h>
#include <linux/profile.h>
#include <linux/module.h>
......@@ -1059,9 +1058,6 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
}
error = security_file_mmap(file, reqprot, prot, flags, addr, 0);
if (error)
return error;
error = ima_file_mmap(file, prot);
if (error)
return error;
......
subdir-y := mdp
subdir- += mdp
subdir-y := mdp genheaders
subdir- += mdp genheaders
hostprogs-y := genheaders
HOST_EXTRACFLAGS += -Isecurity/selinux/include
always := $(hostprogs-y)
clean-files := $(hostprogs-y)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
struct security_class_mapping {
const char *name;
const char *perms[sizeof(unsigned) * 8 + 1];
};
#include "classmap.h"
#include "initial_sid_to_string.h"
#define max(x, y) (((int)(x) > (int)(y)) ? x : y)
const char *progname;
static void usage(void)
{
printf("usage: %s flask.h av_permissions.h\n", progname);
exit(1);
}
static char *stoupperx(const char *s)
{
char *s2 = strdup(s);
char *p;
if (!s2) {
fprintf(stderr, "%s: out of memory\n", progname);
exit(3);
}
for (p = s2; *p; p++)
*p = toupper(*p);
return s2;
}
int main(int argc, char *argv[])
{
int i, j, k;
int isids_len;
FILE *fout;
progname = argv[0];
if (argc < 3)
usage();
fout = fopen(argv[1], "w");
if (!fout) {
fprintf(stderr, "Could not open %s for writing: %s\n",
argv[1], strerror(errno));
exit(2);
}
for (i = 0; secclass_map[i].name; i++) {
struct security_class_mapping *map = &secclass_map[i];
map->name = stoupperx(map->name);
for (j = 0; map->perms[j]; j++)
map->perms[j] = stoupperx(map->perms[j]);
}
isids_len = sizeof(initial_sid_to_string) / sizeof (char *);
for (i = 1; i < isids_len; i++)
initial_sid_to_string[i] = stoupperx(initial_sid_to_string[i]);
fprintf(fout, "/* This file is automatically generated. Do not edit. */\n");
fprintf(fout, "#ifndef _SELINUX_FLASK_H_\n#define _SELINUX_FLASK_H_\n\n");
for (i = 0; secclass_map[i].name; i++) {
struct security_class_mapping *map = &secclass_map[i];
fprintf(fout, "#define SECCLASS_%s", map->name);
for (j = 0; j < max(1, 40 - strlen(map->name)); j++)
fprintf(fout, " ");
fprintf(fout, "%2d\n", i+1);
}
fprintf(fout, "\n");
for (i = 1; i < isids_len; i++) {
char *s = initial_sid_to_string[i];
fprintf(fout, "#define SECINITSID_%s", s);
for (j = 0; j < max(1, 40 - strlen(s)); j++)
fprintf(fout, " ");
fprintf(fout, "%2d\n", i);
}
fprintf(fout, "\n#define SECINITSID_NUM %d\n", i-1);
fprintf(fout, "\n#endif\n");
fclose(fout);
fout = fopen(argv[2], "w");
if (!fout) {
fprintf(stderr, "Could not open %s for writing: %s\n",
argv[2], strerror(errno));
exit(4);
}
fprintf(fout, "/* This file is automatically generated. Do not edit. */\n");
fprintf(fout, "#ifndef _SELINUX_AV_PERMISSIONS_H_\n#define _SELINUX_AV_PERMISSIONS_H_\n\n");
for (i = 0; secclass_map[i].name; i++) {
struct security_class_mapping *map = &secclass_map[i];
for (j = 0; map->perms[j]; j++) {
fprintf(fout, "#define %s__%s", map->name,
map->perms[j]);
for (k = 0; k < max(1, 40 - strlen(map->name) - strlen(map->perms[j])); k++)
fprintf(fout, " ");
fprintf(fout, "0x%08xUL\n", (1<<j));
}
}
fprintf(fout, "\n#endif\n");
fclose(fout);
exit(0);
}
......@@ -29,86 +29,27 @@
#include <unistd.h>
#include <string.h>
#include "flask.h"
static void usage(char *name)
{
printf("usage: %s [-m] policy_file context_file\n", name);
exit(1);
}
static void find_common_name(char *cname, char *dest, int len)
{
char *start, *end;
start = strchr(cname, '_')+1;
end = strchr(start, '_');
if (!start || !end || start-cname > len || end-start > len) {
printf("Error with commons defines\n");
exit(1);
}
strncpy(dest, start, end-start);
dest[end-start] = '\0';
}
#define S_(x) x,
static char *classlist[] = {
#include "class_to_string.h"
NULL
/* Class/perm mapping support */
struct security_class_mapping {
const char *name;
const char *perms[sizeof(unsigned) * 8 + 1];
};
#undef S_
#include "classmap.h"
#include "initial_sid_to_string.h"
#define TB_(x) char *x[] = {
#define TE_(x) NULL };
#define S_(x) x,
#include "common_perm_to_string.h"
#undef TB_
#undef TE_
#undef S_
struct common {
char *cname;
char **perms;
};
struct common common[] = {
#define TB_(x) { #x, x },
#define S_(x)
#define TE_(x)
#include "common_perm_to_string.h"
#undef TB_
#undef TE_
#undef S_
};
#define S_(x, y, z) {x, #y},
struct av_inherit {
int class;
char *common;
};
struct av_inherit av_inherit[] = {
#include "av_inherit.h"
};
#undef S_
#include "av_permissions.h"
#define S_(x, y, z) {x, y, z},
struct av_perms {
int class;
int perm_i;
char *perm_s;
};
struct av_perms av_perms[] = {
#include "av_perm_to_string.h"
};
#undef S_
int main(int argc, char *argv[])
{
int i, j, mls = 0;
int initial_sid_to_string_len;
char **arg, *polout, *ctxout;
int classlist_len, initial_sid_to_string_len;
FILE *fout;
if (argc < 3)
......@@ -127,65 +68,26 @@ int main(int argc, char *argv[])
usage(argv[0]);
}
classlist_len = sizeof(classlist) / sizeof(char *);
/* print out the classes */
for (i=1; i < classlist_len; i++) {
if(classlist[i])
fprintf(fout, "class %s\n", classlist[i]);
else
fprintf(fout, "class user%d\n", i);
}
for (i = 0; secclass_map[i].name; i++)
fprintf(fout, "class %s\n", secclass_map[i].name);
fprintf(fout, "\n");
initial_sid_to_string_len = sizeof(initial_sid_to_string) / sizeof (char *);
/* print out the sids */
for (i=1; i < initial_sid_to_string_len; i++)
for (i = 1; i < initial_sid_to_string_len; i++)
fprintf(fout, "sid %s\n", initial_sid_to_string[i]);
fprintf(fout, "\n");
/* print out the commons */
for (i=0; i< sizeof(common)/sizeof(struct common); i++) {
char cname[101];
find_common_name(common[i].cname, cname, 100);
cname[100] = '\0';
fprintf(fout, "common %s\n{\n", cname);
for (j=0; common[i].perms[j]; j++)
fprintf(fout, "\t%s\n", common[i].perms[j]);
fprintf(fout, "}\n\n");
}
fprintf(fout, "\n");
/* print out the class permissions */
for (i=1; i < classlist_len; i++) {
if (classlist[i]) {
int firstperm = -1, numperms = 0;
fprintf(fout, "class %s\n", classlist[i]);
/* does it inherit from a common? */
for (j=0; j < sizeof(av_inherit)/sizeof(struct av_inherit); j++)
if (av_inherit[j].class == i)
fprintf(fout, "inherits %s\n", av_inherit[j].common);
for (j=0; j < sizeof(av_perms)/sizeof(struct av_perms); j++) {
if (av_perms[j].class == i) {
if (firstperm == -1)
firstperm = j;
numperms++;
}
}
if (!numperms) {
fprintf(fout, "\n");
continue;
}
for (i = 0; secclass_map[i].name; i++) {
struct security_class_mapping *map = &secclass_map[i];
fprintf(fout, "class %s\n", map->name);
fprintf(fout, "{\n");
/* print out the av_perms */
for (j=0; j < numperms; j++) {
fprintf(fout, "\t%s\n", av_perms[firstperm+j].perm_s);
}
for (j = 0; map->perms[j]; j++)
fprintf(fout, "\t%s\n", map->perms[j]);
fprintf(fout, "}\n\n");
}
}
fprintf(fout, "\n");
/* NOW PRINT OUT MLS STUFF */
......@@ -197,31 +99,34 @@ int main(int argc, char *argv[])
/* types, roles, and allows */
fprintf(fout, "type base_t;\n");
fprintf(fout, "role base_r types { base_t };\n");
for (i=1; i < classlist_len; i++) {
if (classlist[i])
fprintf(fout, "allow base_t base_t:%s *;\n", classlist[i]);
else
fprintf(fout, "allow base_t base_t:user%d *;\n", i);
}
for (i = 0; secclass_map[i].name; i++)
fprintf(fout, "allow base_t base_t:%s *;\n",
secclass_map[i].name);
fprintf(fout, "user user_u roles { base_r };\n");
fprintf(fout, "\n");
/* default sids */
for (i=1; i < initial_sid_to_string_len; i++)
for (i = 1; i < initial_sid_to_string_len; i++)
fprintf(fout, "sid %s user_u:base_r:base_t\n", initial_sid_to_string[i]);
fprintf(fout, "\n");
fprintf(fout, "fs_use_xattr ext2 user_u:base_r:base_t;\n");
fprintf(fout, "fs_use_xattr ext3 user_u:base_r:base_t;\n");
fprintf(fout, "fs_use_xattr ext4 user_u:base_r:base_t;\n");
fprintf(fout, "fs_use_xattr jfs user_u:base_r:base_t;\n");
fprintf(fout, "fs_use_xattr xfs user_u:base_r:base_t;\n");
fprintf(fout, "fs_use_xattr reiserfs user_u:base_r:base_t;\n");
fprintf(fout, "fs_use_xattr jffs2 user_u:base_r:base_t;\n");
fprintf(fout, "fs_use_xattr gfs2 user_u:base_r:base_t;\n");
fprintf(fout, "fs_use_xattr lustre user_u:base_r:base_t;\n");
fprintf(fout, "fs_use_task eventpollfs user_u:base_r:base_t;\n");
fprintf(fout, "fs_use_task pipefs user_u:base_r:base_t;\n");
fprintf(fout, "fs_use_task sockfs user_u:base_r:base_t;\n");
fprintf(fout, "fs_use_trans mqueue user_u:base_r:base_t;\n");
fprintf(fout, "fs_use_trans devpts user_u:base_r:base_t;\n");
fprintf(fout, "fs_use_trans hugetlbfs user_u:base_r:base_t;\n");
fprintf(fout, "fs_use_trans tmpfs user_u:base_r:base_t;\n");
fprintf(fout, "fs_use_trans shm user_u:base_r:base_t;\n");
......
......@@ -91,28 +91,6 @@ config SECURITY_PATH
implement pathname based access controls.
If you are unsure how to answer this question, answer N.
config SECURITY_FILE_CAPABILITIES
bool "File POSIX Capabilities"
default n
help
This enables filesystem capabilities, allowing you to give
binaries a subset of root's powers without using setuid 0.
If in doubt, answer N.
config SECURITY_ROOTPLUG
bool "Root Plug Support"
depends on USB=y && SECURITY
help
This is a sample LSM module that should only be used as such.
It prevents any programs running with egid == 0 if a specific
USB device is not present in the system.
See <http://www.linuxjournal.com/article.php?sid=6279> for
more information about this module.
If you are unsure how to answer this question, answer N.
config INTEL_TXT
bool "Enable Intel(R) Trusted Execution Technology (Intel(R) TXT)"
depends on HAVE_INTEL_TXT
......@@ -165,5 +143,37 @@ source security/tomoyo/Kconfig
source security/integrity/ima/Kconfig
choice
prompt "Default security module"
default DEFAULT_SECURITY_SELINUX if SECURITY_SELINUX
default DEFAULT_SECURITY_SMACK if SECURITY_SMACK
default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO
default DEFAULT_SECURITY_DAC
help
Select the security module that will be used by default if the
kernel parameter security= is not specified.
config DEFAULT_SECURITY_SELINUX
bool "SELinux" if SECURITY_SELINUX=y
config DEFAULT_SECURITY_SMACK
bool "Simplified Mandatory Access Control" if SECURITY_SMACK=y
config DEFAULT_SECURITY_TOMOYO
bool "TOMOYO" if SECURITY_TOMOYO=y
config DEFAULT_SECURITY_DAC
bool "Unix Discretionary Access Controls"
endchoice
config DEFAULT_SECURITY
string
default "selinux" if DEFAULT_SECURITY_SELINUX
default "smack" if DEFAULT_SECURITY_SMACK
default "tomoyo" if DEFAULT_SECURITY_TOMOYO
default "" if DEFAULT_SECURITY_DAC
endmenu
......@@ -18,7 +18,6 @@ obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
obj-$(CONFIG_AUDIT) += lsm_audit.o
obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o
obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o
obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
# Object integrity file lists
......
......@@ -308,6 +308,22 @@ static int cap_path_truncate(struct path *path, loff_t length,
{
return 0;
}
static int cap_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
mode_t mode)
{
return 0;
}
static int cap_path_chown(struct path *path, uid_t uid, gid_t gid)
{
return 0;
}
static int cap_path_chroot(struct path *root)
{
return 0;
}
#endif
static int cap_file_permission(struct file *file, int mask)
......@@ -405,7 +421,7 @@ static int cap_kernel_create_files_as(struct cred *new, struct inode *inode)
return 0;
}
static int cap_kernel_module_request(void)
static int cap_kernel_module_request(char *kmod_name)
{
return 0;
}
......@@ -977,6 +993,9 @@ void security_fixup_ops(struct security_operations *ops)
set_to_cap_if_null(ops, path_link);
set_to_cap_if_null(ops, path_rename);
set_to_cap_if_null(ops, path_truncate);
set_to_cap_if_null(ops, path_chmod);
set_to_cap_if_null(ops, path_chown);
set_to_cap_if_null(ops, path_chroot);
#endif
set_to_cap_if_null(ops, file_permission);
set_to_cap_if_null(ops, file_alloc_security);
......
/* Common capabilities, needed by capability.o and root_plug.o
/* Common capabilities, needed by capability.o.
*
* 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
......@@ -173,7 +173,6 @@ int cap_capget(struct task_struct *target, kernel_cap_t *effective,
*/
static inline int cap_inh_is_capped(void)
{
#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
/* they are so limited unless the current task has the CAP_SETPCAP
* capability
......@@ -181,7 +180,6 @@ static inline int cap_inh_is_capped(void)
if (cap_capable(current, current_cred(), CAP_SETPCAP,
SECURITY_CAP_AUDIT) == 0)
return 0;
#endif
return 1;
}
......@@ -239,8 +237,6 @@ static inline void bprm_clear_caps(struct linux_binprm *bprm)
bprm->cap_effective = false;
}
#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
/**
* cap_inode_need_killpriv - Determine if inode change affects privileges
* @dentry: The inode/dentry in being changed with change marked ATTR_KILL_PRIV
......@@ -421,49 +417,6 @@ static int get_file_caps(struct linux_binprm *bprm, bool *effective)
return rc;
}
#else
int cap_inode_need_killpriv(struct dentry *dentry)
{
return 0;
}
int cap_inode_killpriv(struct dentry *dentry)
{
return 0;
}
int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps)
{
memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data));
return -ENODATA;
}
static inline int get_file_caps(struct linux_binprm *bprm, bool *effective)
{
bprm_clear_caps(bprm);
return 0;
}
#endif
/*
* Determine whether a exec'ing process's new permitted capabilities should be
* limited to just what it already has.
*
* This prevents processes that are being ptraced from gaining access to
* CAP_SETPCAP, unless the process they're tracing already has it, and the
* binary they're executing has filecaps that elevate it.
*
* Returns 1 if they should be limited, 0 if they are not.
*/
static inline int cap_limit_ptraced_target(void)
{
#ifndef CONFIG_SECURITY_FILE_CAPABILITIES
if (capable(CAP_SETPCAP))
return 0;
#endif
return 1;
}
/**
* cap_bprm_set_creds - Set up the proposed credentials for execve().
* @bprm: The execution parameters, including the proposed creds
......@@ -523,7 +476,6 @@ int cap_bprm_set_creds(struct linux_binprm *bprm)
new->euid = new->uid;
new->egid = new->gid;
}
if (cap_limit_ptraced_target())
new->cap_permitted = cap_intersect(new->cap_permitted,
old->cap_permitted);
}
......@@ -739,7 +691,6 @@ int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags)
return 0;
}
#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
/*
* Rationale: code calling task_setscheduler, task_setioprio, and
* task_setnice, assumes that
......@@ -820,22 +771,6 @@ static long cap_prctl_drop(struct cred *new, unsigned long cap)
return 0;
}
#else
int cap_task_setscheduler (struct task_struct *p, int policy,
struct sched_param *lp)
{
return 0;
}
int cap_task_setioprio (struct task_struct *p, int ioprio)
{
return 0;
}
int cap_task_setnice (struct task_struct *p, int nice)
{
return 0;
}
#endif
/**
* cap_task_prctl - Implement process control functions for this security module
* @option: The process control function requested
......@@ -866,7 +801,6 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
error = !!cap_raised(new->cap_bset, arg2);
goto no_change;
#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
case PR_CAPBSET_DROP:
error = cap_prctl_drop(new, arg2);
if (error < 0)
......@@ -917,8 +851,6 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
error = new->securebits;
goto no_change;
#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */
case PR_GET_KEEPCAPS:
if (issecure(SECURE_KEEP_CAPS))
error = 1;
......
......@@ -3,6 +3,7 @@
config IMA
bool "Integrity Measurement Architecture(IMA)"
depends on ACPI
depends on SECURITY
select SECURITYFS
select CRYPTO
select CRYPTO_HMAC
......
......@@ -354,6 +354,10 @@ static void dump_common_audit_data(struct audit_buffer *ab,
}
break;
#endif
case LSM_AUDIT_DATA_KMOD:
audit_log_format(ab, " kmod=");
audit_log_untrustedstring(ab, a->u.kmod_name);
break;
} /* switch (a->type) */
}
......
......@@ -33,6 +33,9 @@ int mmap_min_addr_handler(struct ctl_table *table, int write,
{
int ret;
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
update_mmap_min_addr();
......
/*
* Root Plug sample LSM module
*
* Originally written for a Linux Journal.
*
* Copyright (C) 2002 Greg Kroah-Hartman <greg@kroah.com>
*
* Prevents any programs running with egid == 0 if a specific USB device
* is not present in the system. Yes, it can be gotten around, but is a
* nice starting point for people to play with, and learn the LSM
* interface.
*
* If you want to turn this into something with a semblance of security,
* you need to hook the task_* functions also.
*
* See http://www.linuxjournal.com/article.php?sid=6279 for more information
* about this code.
*
* 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, version 2 of the
* License.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/security.h>
#include <linux/usb.h>
#include <linux/moduleparam.h>
/* default is a generic type of usb to serial converter */
static int vendor_id = 0x0557;
static int product_id = 0x2008;
module_param(vendor_id, uint, 0400);
module_param(product_id, uint, 0400);
/* should we print out debug messages */
static int debug = 0;
module_param(debug, bool, 0600);
#define MY_NAME "root_plug"
#define root_dbg(fmt, arg...) \
do { \
if (debug) \
printk(KERN_DEBUG "%s: %s: " fmt , \
MY_NAME , __func__ , \
## arg); \
} while (0)
static int rootplug_bprm_check_security (struct linux_binprm *bprm)
{
struct usb_device *dev;
root_dbg("file %s, e_uid = %d, e_gid = %d\n",
bprm->filename, bprm->cred->euid, bprm->cred->egid);
if (bprm->cred->egid == 0) {
dev = usb_find_device(vendor_id, product_id);
if (!dev) {
root_dbg("e_gid = 0, and device not found, "
"task not allowed to run...\n");
return -EPERM;
}
usb_put_dev(dev);
}
return 0;
}
static struct security_operations rootplug_security_ops = {
.bprm_check_security = rootplug_bprm_check_security,
};
static int __init rootplug_init (void)
{
/* register ourselves with the security framework */
if (register_security (&rootplug_security_ops)) {
printk (KERN_INFO
"Failure registering Root Plug module with the kernel\n");
return -EINVAL;
}
printk (KERN_INFO "Root Plug module initialized, "
"vendor_id = %4.4x, product id = %4.4x\n", vendor_id, product_id);
return 0;
}
security_initcall (rootplug_init);
......@@ -16,9 +16,11 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/security.h>
#include <linux/ima.h>
/* Boot-time LSM user choice */
static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1];
static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
CONFIG_DEFAULT_SECURITY;
/* things that live in capability.c */
extern struct security_operations default_security_ops;
......@@ -79,8 +81,10 @@ __setup("security=", choose_lsm);
*
* Return true if:
* -The passed LSM is the one chosen by user at boot time,
* -or user didn't specify a specific LSM and we're the first to ask
* for registration permission,
* -or the passed LSM is configured as the default and the user did not
* choose an alternate LSM at boot time,
* -or there is no default LSM set and the user didn't specify a
* specific LSM and we're the first to ask for registration permission,
* -or the passed LSM is currently loaded.
* Otherwise, return false.
*/
......@@ -235,7 +239,12 @@ int security_bprm_set_creds(struct linux_binprm *bprm)
int security_bprm_check(struct linux_binprm *bprm)
{
return security_ops->bprm_check_security(bprm);
int ret;
ret = security_ops->bprm_check_security(bprm);
if (ret)
return ret;
return ima_bprm_check(bprm);
}
void security_bprm_committing_creds(struct linux_binprm *bprm)
......@@ -352,12 +361,21 @@ EXPORT_SYMBOL(security_sb_parse_opts_str);
int security_inode_alloc(struct inode *inode)
{
int ret;
inode->i_security = NULL;
return security_ops->inode_alloc_security(inode);
ret = security_ops->inode_alloc_security(inode);
if (ret)
return ret;
ret = ima_inode_alloc(inode);
if (ret)
security_inode_free(inode);
return ret;
}
void security_inode_free(struct inode *inode)
{
ima_inode_free(inode);
security_ops->inode_free_security(inode);
}
......@@ -434,6 +452,26 @@ int security_path_truncate(struct path *path, loff_t length,
return 0;
return security_ops->path_truncate(path, length, time_attrs);
}
int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
mode_t mode)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
return security_ops->path_chmod(dentry, mnt, mode);
}
int security_path_chown(struct path *path, uid_t uid, gid_t gid)
{
if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
return 0;
return security_ops->path_chown(path, uid, gid);
}
int security_path_chroot(struct path *path)
{
return security_ops->path_chroot(path);
}
#endif
int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
......@@ -628,6 +666,8 @@ int security_file_alloc(struct file *file)
void security_file_free(struct file *file)
{
security_ops->file_free_security(file);
if (file->f_dentry)
ima_file_free(file);
}
int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
......@@ -639,7 +679,12 @@ int security_file_mmap(struct file *file, unsigned long reqprot,
unsigned long prot, unsigned long flags,
unsigned long addr, unsigned long addr_only)
{
return security_ops->file_mmap(file, reqprot, prot, flags, addr, addr_only);
int ret;
ret = security_ops->file_mmap(file, reqprot, prot, flags, addr, addr_only);
if (ret)
return ret;
return ima_file_mmap(file, prot);
}
int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
......@@ -719,9 +764,9 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode)
return security_ops->kernel_create_files_as(new, inode);
}
int security_kernel_module_request(void)
int security_kernel_module_request(char *kmod_name)
{
return security_ops->kernel_module_request();
return security_ops->kernel_module_request(kmod_name);
}
int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
......
av_permissions.h
flask.h
......@@ -18,5 +18,13 @@ selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
selinux-$(CONFIG_NETLABEL) += netlabel.o
EXTRA_CFLAGS += -Isecurity/selinux/include
EXTRA_CFLAGS += -Isecurity/selinux -Isecurity/selinux/include
$(obj)/avc.o: $(obj)/flask.h
quiet_cmd_flask = GEN $(obj)/flask.h $(obj)/av_permissions.h
cmd_flask = scripts/selinux/genheaders/genheaders $(obj)/flask.h $(obj)/av_permissions.h
targets += flask.h
$(obj)/flask.h: $(src)/include/classmap.h FORCE
$(call if_changed,flask)
......@@ -31,43 +31,7 @@
#include <net/ipv6.h>
#include "avc.h"
#include "avc_ss.h"
static const struct av_perm_to_string av_perm_to_string[] = {
#define S_(c, v, s) { c, v, s },
#include "av_perm_to_string.h"
#undef S_
};
static const char *class_to_string[] = {
#define S_(s) s,
#include "class_to_string.h"
#undef S_
};
#define TB_(s) static const char *s[] = {
#define TE_(s) };
#define S_(s) s,
#include "common_perm_to_string.h"
#undef TB_
#undef TE_
#undef S_
static const struct av_inherit av_inherit[] = {
#define S_(c, i, b) { .tclass = c,\
.common_pts = common_##i##_perm_to_string,\
.common_base = b },
#include "av_inherit.h"
#undef S_
};
const struct selinux_class_perm selinux_class_perm = {
.av_perm_to_string = av_perm_to_string,
.av_pts_len = ARRAY_SIZE(av_perm_to_string),
.class_to_string = class_to_string,
.cts_len = ARRAY_SIZE(class_to_string),
.av_inherit = av_inherit,
.av_inherit_len = ARRAY_SIZE(av_inherit)
};
#include "classmap.h"
#define AVC_CACHE_SLOTS 512
#define AVC_DEF_CACHE_THRESHOLD 512
......@@ -139,48 +103,24 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass)
*/
static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
{
const char **common_pts = NULL;
u32 common_base = 0;
int i, i2, perm;
const char **perms;
int i, perm;
if (av == 0) {
audit_log_format(ab, " null");
return;
}
for (i = 0; i < ARRAY_SIZE(av_inherit); i++) {
if (av_inherit[i].tclass == tclass) {
common_pts = av_inherit[i].common_pts;
common_base = av_inherit[i].common_base;
break;
}
}
perms = secclass_map[tclass-1].perms;
audit_log_format(ab, " {");
i = 0;
perm = 1;
while (perm < common_base) {
if (perm & av) {
audit_log_format(ab, " %s", common_pts[i]);
av &= ~perm;
}
i++;
perm <<= 1;
}
while (i < sizeof(av) * 8) {
if (perm & av) {
for (i2 = 0; i2 < ARRAY_SIZE(av_perm_to_string); i2++) {
if ((av_perm_to_string[i2].tclass == tclass) &&
(av_perm_to_string[i2].value == perm))
break;
}
if (i2 < ARRAY_SIZE(av_perm_to_string)) {
audit_log_format(ab, " %s",
av_perm_to_string[i2].name);
while (i < (sizeof(av) * 8)) {
if ((perm & av) && perms[i]) {
audit_log_format(ab, " %s", perms[i]);
av &= ~perm;
}
}
i++;
perm <<= 1;
}
......@@ -219,8 +159,8 @@ static void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tcla
kfree(scontext);
}
BUG_ON(tclass >= ARRAY_SIZE(class_to_string) || !class_to_string[tclass]);
audit_log_format(ab, " tclass=%s", class_to_string[tclass]);
BUG_ON(tclass >= ARRAY_SIZE(secclass_map));
audit_log_format(ab, " tclass=%s", secclass_map[tclass-1].name);
}
/**
......
......@@ -91,7 +91,6 @@
#define NUM_SEL_MNT_OPTS 5
extern unsigned int policydb_loaded_version;
extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
extern struct security_operations *security_ops;
......@@ -3338,9 +3337,18 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
return 0;
}
static int selinux_kernel_module_request(void)
static int selinux_kernel_module_request(char *kmod_name)
{
return task_has_system(current, SYSTEM__MODULE_REQUEST);
u32 sid;
struct common_audit_data ad;
sid = task_sid(current);
COMMON_AUDIT_DATA_INIT(&ad, KMOD);
ad.u.kmod_name = kmod_name;
return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
SYSTEM__MODULE_REQUEST, &ad);
}
static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
......@@ -4714,10 +4722,7 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
if (err)
return err;
if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS)
err = selinux_nlmsg_perm(sk, skb);
return err;
return selinux_nlmsg_perm(sk, skb);
}
static int selinux_netlink_recv(struct sk_buff *skb, int capability)
......@@ -5830,12 +5835,12 @@ int selinux_disable(void)
selinux_disabled = 1;
selinux_enabled = 0;
/* Try to destroy the avc node cache */
avc_disable();
/* Reset security_ops to the secondary module, dummy or capability. */
security_ops = secondary_ops;
/* Try to destroy the avc node cache */
avc_disable();
/* Unregister netfilter hooks. */
selinux_nf_ip_exit();
......
/* This file is automatically generated. Do not edit. */
S_(SECCLASS_DIR, file, 0x00020000UL)
S_(SECCLASS_FILE, file, 0x00020000UL)
S_(SECCLASS_LNK_FILE, file, 0x00020000UL)
S_(SECCLASS_CHR_FILE, file, 0x00020000UL)
S_(SECCLASS_BLK_FILE, file, 0x00020000UL)
S_(SECCLASS_SOCK_FILE, file, 0x00020000UL)
S_(SECCLASS_FIFO_FILE, file, 0x00020000UL)
S_(SECCLASS_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_TCP_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_UDP_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_RAWIP_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_NETLINK_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_PACKET_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_KEY_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_UNIX_STREAM_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_UNIX_DGRAM_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_TUN_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_IPC, ipc, 0x00000200UL)
S_(SECCLASS_SEM, ipc, 0x00000200UL)
S_(SECCLASS_MSGQ, ipc, 0x00000200UL)
S_(SECCLASS_SHM, ipc, 0x00000200UL)
S_(SECCLASS_NETLINK_ROUTE_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_NETLINK_FIREWALL_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_NETLINK_TCPDIAG_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_NETLINK_NFLOG_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_NETLINK_XFRM_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_NETLINK_SELINUX_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_NETLINK_AUDIT_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_NETLINK_IP6FW_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_NETLINK_DNRT_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_APPLETALK_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_DCCP_SOCKET, socket, 0x00400000UL)
This diff is collapsed.
This diff is collapsed.
......@@ -10,26 +10,13 @@
int avc_ss_reset(u32 seqno);
struct av_perm_to_string {
u16 tclass;
u32 value;
/* Class/perm mapping support */
struct security_class_mapping {
const char *name;
const char *perms[sizeof(u32) * 8 + 1];
};
struct av_inherit {
const char **common_pts;
u32 common_base;
u16 tclass;
};
struct selinux_class_perm {
const struct av_perm_to_string *av_perm_to_string;
u32 av_pts_len;
u32 cts_len;
const char **class_to_string;
const struct av_inherit *av_inherit;
u32 av_inherit_len;
};
extern struct security_class_mapping secclass_map[];
#endif /* _SELINUX_AVC_SS_H_ */
/* This file is automatically generated. Do not edit. */
/*
* Security object class definitions
*/
S_(NULL)
S_("security")
S_("process")
S_("system")
S_("capability")
S_("filesystem")
S_("file")
S_("dir")
S_("fd")
S_("lnk_file")
S_("chr_file")
S_("blk_file")
S_("sock_file")
S_("fifo_file")
S_("socket")
S_("tcp_socket")
S_("udp_socket")
S_("rawip_socket")
S_("node")
S_("netif")
S_("netlink_socket")
S_("packet_socket")
S_("key_socket")
S_("unix_stream_socket")
S_("unix_dgram_socket")
S_("sem")
S_("msg")
S_("msgq")
S_("shm")
S_("ipc")
S_(NULL)
S_(NULL)
S_(NULL)
S_(NULL)
S_(NULL)
S_(NULL)
S_(NULL)
S_(NULL)
S_(NULL)
S_(NULL)
S_(NULL)
S_(NULL)
S_(NULL)
S_("netlink_route_socket")
S_("netlink_firewall_socket")
S_("netlink_tcpdiag_socket")
S_("netlink_nflog_socket")
S_("netlink_xfrm_socket")
S_("netlink_selinux_socket")
S_("netlink_audit_socket")
S_("netlink_ip6fw_socket")
S_("netlink_dnrt_socket")
S_(NULL)
S_(NULL)
S_("association")
S_("netlink_kobject_uevent_socket")
S_("appletalk_socket")
S_("packet")
S_("key")
S_(NULL)
S_("dccp_socket")
S_("memprotect")
S_(NULL)
S_(NULL)
S_(NULL)
S_(NULL)
S_(NULL)
S_(NULL)
S_("peer")
S_("capability2")
S_(NULL)
S_(NULL)
S_(NULL)
S_(NULL)
S_("kernel_service")
S_("tun_socket")
#define COMMON_FILE_SOCK_PERMS "ioctl", "read", "write", "create", \
"getattr", "setattr", "lock", "relabelfrom", "relabelto", "append"
#define COMMON_FILE_PERMS COMMON_FILE_SOCK_PERMS, "unlink", "link", \
"rename", "execute", "swapon", "quotaon", "mounton"
#define COMMON_SOCK_PERMS COMMON_FILE_SOCK_PERMS, "bind", "connect", \
"listen", "accept", "getopt", "setopt", "shutdown", "recvfrom", \
"sendto", "recv_msg", "send_msg", "name_bind"
#define COMMON_IPC_PERMS "create", "destroy", "getattr", "setattr", "read", \
"write", "associate", "unix_read", "unix_write"
struct security_class_mapping secclass_map[] = {
{ "security",
{ "compute_av", "compute_create", "compute_member",
"check_context", "load_policy", "compute_relabel",
"compute_user", "setenforce", "setbool", "setsecparam",
"setcheckreqprot", NULL } },
{ "process",
{ "fork", "transition", "sigchld", "sigkill",
"sigstop", "signull", "signal", "ptrace", "getsched", "setsched",
"getsession", "getpgid", "setpgid", "getcap", "setcap", "share",
"getattr", "setexec", "setfscreate", "noatsecure", "siginh",
"setrlimit", "rlimitinh", "dyntransition", "setcurrent",
"execmem", "execstack", "execheap", "setkeycreate",
"setsockcreate", NULL } },
{ "system",
{ "ipc_info", "syslog_read", "syslog_mod",
"syslog_console", "module_request", NULL } },
{ "capability",
{ "chown", "dac_override", "dac_read_search",
"fowner", "fsetid", "kill", "setgid", "setuid", "setpcap",
"linux_immutable", "net_bind_service", "net_broadcast",
"net_admin", "net_raw", "ipc_lock", "ipc_owner", "sys_module",
"sys_rawio", "sys_chroot", "sys_ptrace", "sys_pacct", "sys_admin",
"sys_boot", "sys_nice", "sys_resource", "sys_time",
"sys_tty_config", "mknod", "lease", "audit_write",
"audit_control", "setfcap", NULL } },
{ "filesystem",
{ "mount", "remount", "unmount", "getattr",
"relabelfrom", "relabelto", "transition", "associate", "quotamod",
"quotaget", NULL } },
{ "file",
{ COMMON_FILE_PERMS,
"execute_no_trans", "entrypoint", "execmod", "open", NULL } },
{ "dir",
{ COMMON_FILE_PERMS, "add_name", "remove_name",
"reparent", "search", "rmdir", "open", NULL } },
{ "fd", { "use", NULL } },
{ "lnk_file",
{ COMMON_FILE_PERMS, NULL } },
{ "chr_file",
{ COMMON_FILE_PERMS,
"execute_no_trans", "entrypoint", "execmod", "open", NULL } },
{ "blk_file",
{ COMMON_FILE_PERMS, "open", NULL } },
{ "sock_file",
{ COMMON_FILE_PERMS, "open", NULL } },
{ "fifo_file",
{ COMMON_FILE_PERMS, "open", NULL } },
{ "socket",
{ COMMON_SOCK_PERMS, NULL } },
{ "tcp_socket",
{ COMMON_SOCK_PERMS,
"connectto", "newconn", "acceptfrom", "node_bind", "name_connect",
NULL } },
{ "udp_socket",
{ COMMON_SOCK_PERMS,
"node_bind", NULL } },
{ "rawip_socket",
{ COMMON_SOCK_PERMS,
"node_bind", NULL } },
{ "node",
{ "tcp_recv", "tcp_send", "udp_recv", "udp_send",
"rawip_recv", "rawip_send", "enforce_dest",
"dccp_recv", "dccp_send", "recvfrom", "sendto", NULL } },
{ "netif",
{ "tcp_recv", "tcp_send", "udp_recv", "udp_send",
"rawip_recv", "rawip_send", "dccp_recv", "dccp_send",
"ingress", "egress", NULL } },
{ "netlink_socket",
{ COMMON_SOCK_PERMS, NULL } },
{ "packet_socket",
{ COMMON_SOCK_PERMS, NULL } },
{ "key_socket",
{ COMMON_SOCK_PERMS, NULL } },
{ "unix_stream_socket",
{ COMMON_SOCK_PERMS, "connectto", "newconn", "acceptfrom", NULL
} },
{ "unix_dgram_socket",
{ COMMON_SOCK_PERMS, NULL
} },
{ "sem",
{ COMMON_IPC_PERMS, NULL } },
{ "msg", { "send", "receive", NULL } },
{ "msgq",
{ COMMON_IPC_PERMS, "enqueue", NULL } },
{ "shm",
{ COMMON_IPC_PERMS, "lock", NULL } },
{ "ipc",
{ COMMON_IPC_PERMS, NULL } },
{ "netlink_route_socket",
{ COMMON_SOCK_PERMS,
"nlmsg_read", "nlmsg_write", NULL } },
{ "netlink_firewall_socket",
{ COMMON_SOCK_PERMS,
"nlmsg_read", "nlmsg_write", NULL } },
{ "netlink_tcpdiag_socket",
{ COMMON_SOCK_PERMS,
"nlmsg_read", "nlmsg_write", NULL } },
{ "netlink_nflog_socket",
{ COMMON_SOCK_PERMS, NULL } },
{ "netlink_xfrm_socket",
{ COMMON_SOCK_PERMS,
"nlmsg_read", "nlmsg_write", NULL } },
{ "netlink_selinux_socket",
{ COMMON_SOCK_PERMS, NULL } },
{ "netlink_audit_socket",
{ COMMON_SOCK_PERMS,
"nlmsg_read", "nlmsg_write", "nlmsg_relay", "nlmsg_readpriv",
"nlmsg_tty_audit", NULL } },
{ "netlink_ip6fw_socket",
{ COMMON_SOCK_PERMS,
"nlmsg_read", "nlmsg_write", NULL } },
{ "netlink_dnrt_socket",
{ COMMON_SOCK_PERMS, NULL } },
{ "association",
{ "sendto", "recvfrom", "setcontext", "polmatch", NULL } },
{ "netlink_kobject_uevent_socket",
{ COMMON_SOCK_PERMS, NULL } },
{ "appletalk_socket",
{ COMMON_SOCK_PERMS, NULL } },
{ "packet",
{ "send", "recv", "relabelto", "flow_in", "flow_out",
"forward_in", "forward_out", NULL } },
{ "key",
{ "view", "read", "write", "search", "link", "setattr", "create",
NULL } },
{ "dccp_socket",
{ COMMON_SOCK_PERMS,
"node_bind", "name_connect", NULL } },
{ "memprotect", { "mmap_zero", NULL } },
{ "peer", { "recv", NULL } },
{ "capability2", { "mac_override", "mac_admin", NULL } },
{ "kernel_service", { "use_as_override", "create_files_as", NULL } },
{ "tun_socket",
{ COMMON_SOCK_PERMS, NULL } },
{ NULL }
};
/* This file is automatically generated. Do not edit. */
TB_(common_file_perm_to_string)
S_("ioctl")
S_("read")
S_("write")
S_("create")
S_("getattr")
S_("setattr")
S_("lock")
S_("relabelfrom")
S_("relabelto")
S_("append")
S_("unlink")
S_("link")
S_("rename")
S_("execute")
S_("swapon")
S_("quotaon")
S_("mounton")
TE_(common_file_perm_to_string)
TB_(common_socket_perm_to_string)
S_("ioctl")
S_("read")
S_("write")
S_("create")
S_("getattr")
S_("setattr")
S_("lock")
S_("relabelfrom")
S_("relabelto")
S_("append")
S_("bind")
S_("connect")
S_("listen")
S_("accept")
S_("getopt")
S_("setopt")
S_("shutdown")
S_("recvfrom")
S_("sendto")
S_("recv_msg")
S_("send_msg")
S_("name_bind")
TE_(common_socket_perm_to_string)
TB_(common_ipc_perm_to_string)
S_("create")
S_("destroy")
S_("getattr")
S_("setattr")
S_("read")
S_("write")
S_("associate")
S_("unix_read")
S_("unix_write")
TE_(common_ipc_perm_to_string)
/* This file is automatically generated. Do not edit. */
#ifndef _SELINUX_FLASK_H_
#define _SELINUX_FLASK_H_
/*
* Security object class definitions
*/
#define SECCLASS_SECURITY 1
#define SECCLASS_PROCESS 2
#define SECCLASS_SYSTEM 3
#define SECCLASS_CAPABILITY 4
#define SECCLASS_FILESYSTEM 5
#define SECCLASS_FILE 6
#define SECCLASS_DIR 7
#define SECCLASS_FD 8
#define SECCLASS_LNK_FILE 9
#define SECCLASS_CHR_FILE 10
#define SECCLASS_BLK_FILE 11
#define SECCLASS_SOCK_FILE 12
#define SECCLASS_FIFO_FILE 13
#define SECCLASS_SOCKET 14
#define SECCLASS_TCP_SOCKET 15
#define SECCLASS_UDP_SOCKET 16
#define SECCLASS_RAWIP_SOCKET 17
#define SECCLASS_NODE 18
#define SECCLASS_NETIF 19
#define SECCLASS_NETLINK_SOCKET 20
#define SECCLASS_PACKET_SOCKET 21
#define SECCLASS_KEY_SOCKET 22
#define SECCLASS_UNIX_STREAM_SOCKET 23
#define SECCLASS_UNIX_DGRAM_SOCKET 24
#define SECCLASS_SEM 25
#define SECCLASS_MSG 26
#define SECCLASS_MSGQ 27
#define SECCLASS_SHM 28
#define SECCLASS_IPC 29
#define SECCLASS_NETLINK_ROUTE_SOCKET 43
#define SECCLASS_NETLINK_FIREWALL_SOCKET 44
#define SECCLASS_NETLINK_TCPDIAG_SOCKET 45
#define SECCLASS_NETLINK_NFLOG_SOCKET 46
#define SECCLASS_NETLINK_XFRM_SOCKET 47
#define SECCLASS_NETLINK_SELINUX_SOCKET 48
#define SECCLASS_NETLINK_AUDIT_SOCKET 49
#define SECCLASS_NETLINK_IP6FW_SOCKET 50
#define SECCLASS_NETLINK_DNRT_SOCKET 51
#define SECCLASS_ASSOCIATION 54
#define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET 55
#define SECCLASS_APPLETALK_SOCKET 56
#define SECCLASS_PACKET 57
#define SECCLASS_KEY 58
#define SECCLASS_DCCP_SOCKET 60
#define SECCLASS_MEMPROTECT 61
#define SECCLASS_PEER 68
#define SECCLASS_CAPABILITY2 69
#define SECCLASS_KERNEL_SERVICE 74
#define SECCLASS_TUN_SOCKET 75
/*
* Security identifier indices for initial entities
*/
#define SECINITSID_KERNEL 1
#define SECINITSID_SECURITY 2
#define SECINITSID_UNLABELED 3
#define SECINITSID_FS 4
#define SECINITSID_FILE 5
#define SECINITSID_FILE_LABELS 6
#define SECINITSID_INIT 7
#define SECINITSID_ANY_SOCKET 8
#define SECINITSID_PORT 9
#define SECINITSID_NETIF 10
#define SECINITSID_NETMSG 11
#define SECINITSID_NODE 12
#define SECINITSID_IGMP_PACKET 13
#define SECINITSID_ICMP_SOCKET 14
#define SECINITSID_TCP_SOCKET 15
#define SECINITSID_SYSCTL_MODPROBE 16
#define SECINITSID_SYSCTL 17
#define SECINITSID_SYSCTL_FS 18
#define SECINITSID_SYSCTL_KERNEL 19
#define SECINITSID_SYSCTL_NET 20
#define SECINITSID_SYSCTL_NET_UNIX 21
#define SECINITSID_SYSCTL_VM 22
#define SECINITSID_SYSCTL_DEV 23
#define SECINITSID_KMOD 24
#define SECINITSID_POLICY 25
#define SECINITSID_SCMP_PACKET 26
#define SECINITSID_DEVNULL 27
#define SECINITSID_NUM 27
#endif
......@@ -100,9 +100,16 @@ int security_compute_av(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
struct av_decision *avd);
int security_compute_av_user(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
struct av_decision *avd);
int security_transition_sid(u32 ssid, u32 tsid,
u16 tclass, u32 *out_sid);
int security_transition_sid_user(u32 ssid, u32 tsid,
u16 tclass, u32 *out_sid);
int security_member_sid(u32 ssid, u32 tsid,
u16 tclass, u32 *out_sid);
......
......@@ -522,7 +522,7 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size)
if (length < 0)
goto out2;
length = security_compute_av(ssid, tsid, tclass, req, &avd);
length = security_compute_av_user(ssid, tsid, tclass, req, &avd);
if (length < 0)
goto out2;
......@@ -571,7 +571,7 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
if (length < 0)
goto out2;
length = security_transition_sid(ssid, tsid, tclass, &newsid);
length = security_transition_sid_user(ssid, tsid, tclass, &newsid);
if (length < 0)
goto out2;
......
......@@ -2,7 +2,7 @@
# Makefile for building the SELinux security server as part of the kernel tree.
#
EXTRA_CFLAGS += -Isecurity/selinux/include
EXTRA_CFLAGS += -Isecurity/selinux -Isecurity/selinux/include
obj-y := ss.o
ss-y := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o conditional.o mls.o
......
......@@ -532,7 +532,7 @@ int mls_compute_sid(struct context *scontext,
}
/* Fallthrough */
case AVTAB_CHANGE:
if (tclass == SECCLASS_PROCESS)
if (tclass == policydb.process_class)
/* Use the process MLS attributes. */
return mls_context_cpy(newcontext, scontext);
else
......
......@@ -713,7 +713,6 @@ void policydb_destroy(struct policydb *p)
ebitmap_destroy(&p->type_attr_map[i]);
}
kfree(p->type_attr_map);
kfree(p->undefined_perms);
ebitmap_destroy(&p->policycaps);
ebitmap_destroy(&p->permissive_map);
......@@ -1640,6 +1639,40 @@ static int policydb_bounds_sanity_check(struct policydb *p)
extern int ss_initialized;
u16 string_to_security_class(struct policydb *p, const char *name)
{
struct class_datum *cladatum;
cladatum = hashtab_search(p->p_classes.table, name);
if (!cladatum)
return 0;
return cladatum->value;
}
u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name)
{
struct class_datum *cladatum;
struct perm_datum *perdatum = NULL;
struct common_datum *comdatum;
if (!tclass || tclass > p->p_classes.nprim)
return 0;
cladatum = p->class_val_to_struct[tclass-1];
comdatum = cladatum->comdatum;
if (comdatum)
perdatum = hashtab_search(comdatum->permissions.table,
name);
if (!perdatum)
perdatum = hashtab_search(cladatum->permissions.table,
name);
if (!perdatum)
return 0;
return 1U << (perdatum->value-1);
}
/*
* Read the configuration data from a policy database binary
* representation file into a policy database structure.
......@@ -1861,6 +1894,16 @@ int policydb_read(struct policydb *p, void *fp)
if (rc)
goto bad;
p->process_class = string_to_security_class(p, "process");
if (!p->process_class)
goto bad;
p->process_trans_perms = string_to_av_perm(p, p->process_class,
"transition");
p->process_trans_perms |= string_to_av_perm(p, p->process_class,
"dyntransition");
if (!p->process_trans_perms)
goto bad;
for (i = 0; i < info->ocon_num; i++) {
rc = next_entry(buf, fp, sizeof(u32));
if (rc < 0)
......@@ -2101,7 +2144,7 @@ int policydb_read(struct policydb *p, void *fp)
goto bad;
rt->target_class = le32_to_cpu(buf[0]);
} else
rt->target_class = SECCLASS_PROCESS;
rt->target_class = p->process_class;
if (!policydb_type_isvalid(p, rt->source_type) ||
!policydb_type_isvalid(p, rt->target_type) ||
!policydb_class_isvalid(p, rt->target_class)) {
......
......@@ -254,7 +254,9 @@ struct policydb {
unsigned int reject_unknown : 1;
unsigned int allow_unknown : 1;
u32 *undefined_perms;
u16 process_class;
u32 process_trans_perms;
};
extern void policydb_destroy(struct policydb *p);
......@@ -295,5 +297,8 @@ static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes)
return 0;
}
extern u16 string_to_security_class(struct policydb *p, const char *name);
extern u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name);
#endif /* _SS_POLICYDB_H_ */
This diff is collapsed.
......@@ -187,6 +187,8 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
const s8 pattern_type, const s8 end_type,
const char *function)
{
const char *const start = filename;
bool in_repetition = false;
bool contains_pattern = false;
unsigned char c;
unsigned char d;
......@@ -212,9 +214,13 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
if (c == '/')
goto out;
}
while ((c = *filename++) != '\0') {
while (1) {
c = *filename++;
if (!c)
break;
if (c == '\\') {
switch ((c = *filename++)) {
c = *filename++;
switch (c) {
case '\\': /* "\\" */
continue;
case '$': /* "\$" */
......@@ -231,6 +237,22 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
break; /* Must not contain pattern */
contains_pattern = true;
continue;
case '{': /* "/\{" */
if (filename - 3 < start ||
*(filename - 3) != '/')
break;
if (pattern_type == -1)
break; /* Must not contain pattern */
contains_pattern = true;
in_repetition = true;
continue;
case '}': /* "\}/" */
if (*filename != '/')
break;
if (!in_repetition)
break;
in_repetition = false;
continue;
case '0': /* "\ooo" */
case '1':
case '2':
......@@ -246,6 +268,8 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
continue; /* pattern is not \000 */
}
goto out;
} else if (in_repetition && c == '/') {
goto out;
} else if (tomoyo_is_invalid(c)) {
goto out;
}
......@@ -254,6 +278,8 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
if (!contains_pattern)
goto out;
}
if (in_repetition)
goto out;
return true;
out:
printk(KERN_DEBUG "%s: Invalid pathname '%s'\n", function,
......@@ -359,33 +385,6 @@ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
return NULL;
}
/**
* tomoyo_path_depth - Evaluate the number of '/' in a string.
*
* @pathname: The string to evaluate.
*
* Returns path depth of the string.
*
* I score 2 for each of the '/' in the @pathname
* and score 1 if the @pathname ends with '/'.
*/
static int tomoyo_path_depth(const char *pathname)
{
int i = 0;
if (pathname) {
const char *ep = pathname + strlen(pathname);
if (pathname < ep--) {
if (*ep != '/')
i++;
while (pathname <= ep)
if (*ep-- == '/')
i += 2;
}
}
return i;
}
/**
* tomoyo_const_part_length - Evaluate the initial length without a pattern in a token.
*
......@@ -444,11 +443,10 @@ void tomoyo_fill_path_info(struct tomoyo_path_info *ptr)
ptr->is_dir = len && (name[len - 1] == '/');
ptr->is_patterned = (ptr->const_len < len);
ptr->hash = full_name_hash(name, len);
ptr->depth = tomoyo_path_depth(name);
}
/**
* tomoyo_file_matches_to_pattern2 - Pattern matching without '/' character
* tomoyo_file_matches_pattern2 - Pattern matching without '/' character
* and "\-" pattern.
*
* @filename: The start of string to check.
......@@ -458,7 +456,7 @@ void tomoyo_fill_path_info(struct tomoyo_path_info *ptr)
*
* Returns true if @filename matches @pattern, false otherwise.
*/
static bool tomoyo_file_matches_to_pattern2(const char *filename,
static bool tomoyo_file_matches_pattern2(const char *filename,
const char *filename_end,
const char *pattern,
const char *pattern_end)
......@@ -519,7 +517,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename,
case '*':
case '@':
for (i = 0; i <= filename_end - filename; i++) {
if (tomoyo_file_matches_to_pattern2(
if (tomoyo_file_matches_pattern2(
filename + i, filename_end,
pattern + 1, pattern_end))
return true;
......@@ -550,7 +548,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename,
j++;
}
for (i = 1; i <= j; i++) {
if (tomoyo_file_matches_to_pattern2(
if (tomoyo_file_matches_pattern2(
filename + i, filename_end,
pattern + 1, pattern_end))
return true;
......@@ -567,7 +565,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename,
}
/**
* tomoyo_file_matches_to_pattern - Pattern matching without without '/' character.
* tomoyo_file_matches_pattern - Pattern matching without without '/' character.
*
* @filename: The start of string to check.
* @filename_end: The end of string to check.
......@@ -576,7 +574,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename,
*
* Returns true if @filename matches @pattern, false otherwise.
*/
static bool tomoyo_file_matches_to_pattern(const char *filename,
static bool tomoyo_file_matches_pattern(const char *filename,
const char *filename_end,
const char *pattern,
const char *pattern_end)
......@@ -589,7 +587,7 @@ static bool tomoyo_file_matches_to_pattern(const char *filename,
/* Split at "\-" pattern. */
if (*pattern++ != '\\' || *pattern++ != '-')
continue;
result = tomoyo_file_matches_to_pattern2(filename,
result = tomoyo_file_matches_pattern2(filename,
filename_end,
pattern_start,
pattern - 2);
......@@ -600,13 +598,79 @@ static bool tomoyo_file_matches_to_pattern(const char *filename,
first = false;
pattern_start = pattern;
}
result = tomoyo_file_matches_to_pattern2(filename, filename_end,
result = tomoyo_file_matches_pattern2(filename, filename_end,
pattern_start, pattern_end);
return first ? result : !result;
}
/**
* tomoyo_path_matches_pattern2 - Do pathname pattern matching.
*
* @f: The start of string to check.
* @p: The start of pattern to compare.
*
* Returns true if @f matches @p, false otherwise.
*/
static bool tomoyo_path_matches_pattern2(const char *f, const char *p)
{
const char *f_delimiter;
const char *p_delimiter;
while (*f && *p) {
f_delimiter = strchr(f, '/');
if (!f_delimiter)
f_delimiter = f + strlen(f);
p_delimiter = strchr(p, '/');
if (!p_delimiter)
p_delimiter = p + strlen(p);
if (*p == '\\' && *(p + 1) == '{')
goto recursive;
if (!tomoyo_file_matches_pattern(f, f_delimiter, p,
p_delimiter))
return false;
f = f_delimiter;
if (*f)
f++;
p = p_delimiter;
if (*p)
p++;
}
/* Ignore trailing "\*" and "\@" in @pattern. */
while (*p == '\\' &&
(*(p + 1) == '*' || *(p + 1) == '@'))
p += 2;
return !*f && !*p;
recursive:
/*
* The "\{" pattern is permitted only after '/' character.
* This guarantees that below "*(p - 1)" is safe.
* Also, the "\}" pattern is permitted only before '/' character
* so that "\{" + "\}" pair will not break the "\-" operator.
*/
if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' ||
*(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\')
return false; /* Bad pattern. */
do {
/* Compare current component with pattern. */
if (!tomoyo_file_matches_pattern(f, f_delimiter, p + 2,
p_delimiter - 2))
break;
/* Proceed to next component. */
f = f_delimiter;
if (!*f)
break;
f++;
/* Continue comparison. */
if (tomoyo_path_matches_pattern2(f, p_delimiter + 1))
return true;
f_delimiter = strchr(f, '/');
} while (f_delimiter);
return false; /* Not matched. */
}
/**
* tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern.
*
* @filename: The filename to check.
* @pattern: The pattern to compare.
*
......@@ -615,24 +679,24 @@ static bool tomoyo_file_matches_to_pattern(const char *filename,
* The following patterns are available.
* \\ \ itself.
* \ooo Octal representation of a byte.
* \* More than or equals to 0 character other than '/'.
* \@ More than or equals to 0 character other than '/' or '.'.
* \* Zero or more repetitions of characters other than '/'.
* \@ Zero or more repetitions of characters other than '/' or '.'.
* \? 1 byte character other than '/'.
* \$ More than or equals to 1 decimal digit.
* \$ One or more repetitions of decimal digits.
* \+ 1 decimal digit.
* \X More than or equals to 1 hexadecimal digit.
* \X One or more repetitions of hexadecimal digits.
* \x 1 hexadecimal digit.
* \A More than or equals to 1 alphabet character.
* \A One or more repetitions of alphabet characters.
* \a 1 alphabet character.
*
* \- Subtraction operator.
*
* /\{dir\}/ '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/
* /dir/dir/dir/ ).
*/
bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
const struct tomoyo_path_info *pattern)
{
/*
if (!filename || !pattern)
return false;
*/
const char *f = filename->name;
const char *p = pattern->name;
const int len = pattern->const_len;
......@@ -640,37 +704,15 @@ bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
/* If @pattern doesn't contain pattern, I can use strcmp(). */
if (!pattern->is_patterned)
return !tomoyo_pathcmp(filename, pattern);
/* Dont compare if the number of '/' differs. */
if (filename->depth != pattern->depth)
/* Don't compare directory and non-directory. */
if (filename->is_dir != pattern->is_dir)
return false;
/* Compare the initial length without patterns. */
if (strncmp(f, p, len))
return false;
f += len;
p += len;
/* Main loop. Compare each directory component. */
while (*f && *p) {
const char *f_delimiter = strchr(f, '/');
const char *p_delimiter = strchr(p, '/');
if (!f_delimiter)
f_delimiter = f + strlen(f);
if (!p_delimiter)
p_delimiter = p + strlen(p);
if (!tomoyo_file_matches_to_pattern(f, f_delimiter,
p, p_delimiter))
return false;
f = f_delimiter;
if (*f)
f++;
p = p_delimiter;
if (*p)
p++;
}
/* Ignore trailing "\*" and "\@" in @pattern. */
while (*p == '\\' &&
(*(p + 1) == '*' || *(p + 1) == '@'))
p += 2;
return !*f && !*p;
return tomoyo_path_matches_pattern2(f, p);
}
/**
......
......@@ -56,9 +56,6 @@ struct tomoyo_page_buffer {
* (5) "is_patterned" is a bool which is true if "name" contains wildcard
* characters, false otherwise. This allows TOMOYO to use "hash" and
* strcmp() for string comparison if "is_patterned" is false.
* (6) "depth" is calculated using the number of "/" characters in "name".
* This allows TOMOYO to avoid comparing two pathnames which never match
* (e.g. whether "/var/www/html/index.html" matches "/tmp/sh-thd-\$").
*/
struct tomoyo_path_info {
const char *name;
......@@ -66,7 +63,6 @@ struct tomoyo_path_info {
u16 const_len; /* = tomoyo_const_part_length(name) */
bool is_dir; /* = tomoyo_strendswith(name, "/") */
bool is_patterned; /* = tomoyo_path_contains_pattern(name) */
u16 depth; /* = tomoyo_path_depth(name) */
};
/*
......
......@@ -13,6 +13,8 @@
#include <linux/mount.h>
#include <linux/mnt_namespace.h>
#include <linux/fs_struct.h>
#include <linux/hash.h>
#include "common.h"
#include "realpath.h"
......@@ -263,7 +265,8 @@ static unsigned int tomoyo_quota_for_savename;
* table. Frequency of appending strings is very low. So we don't need
* large (e.g. 64k) hash size. 256 will be sufficient.
*/
#define TOMOYO_MAX_HASH 256
#define TOMOYO_HASH_BITS 8
#define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS)
/*
* tomoyo_name_entry is a structure which is used for linking
......@@ -315,6 +318,7 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name)
struct tomoyo_free_memory_block_list *fmb;
int len;
char *cp;
struct list_head *head;
if (!name)
return NULL;
......@@ -325,9 +329,10 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name)
return NULL;
}
hash = full_name_hash((const unsigned char *) name, len - 1);
head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)];
mutex_lock(&lock);
list_for_each_entry(ptr, &tomoyo_name_list[hash % TOMOYO_MAX_HASH],
list) {
list_for_each_entry(ptr, head, list) {
if (hash == ptr->entry.hash && !strcmp(name, ptr->entry.name))
goto out;
}
......@@ -365,7 +370,7 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name)
tomoyo_fill_path_info(&ptr->entry);
fmb->ptr += len;
fmb->len -= len;
list_add_tail(&ptr->list, &tomoyo_name_list[hash % TOMOYO_MAX_HASH]);
list_add_tail(&ptr->list, head);
if (fmb->len == 0) {
list_del(&fmb->list);
kfree(fmb);
......
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