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* ...@@ -65,6 +65,7 @@ aicdb.h*
asm-offsets.h asm-offsets.h
asm_offsets.h asm_offsets.h
autoconf.h* autoconf.h*
av_permissions.h
bbootsect bbootsect
bin2c bin2c
binkernel.spec binkernel.spec
...@@ -95,12 +96,14 @@ docproc ...@@ -95,12 +96,14 @@ docproc
elf2ecoff elf2ecoff
elfconfig.h* elfconfig.h*
fixdep fixdep
flask.h
fore200e_mkfirm fore200e_mkfirm
fore200e_pca_fw.c* fore200e_pca_fw.c*
gconf gconf
gen-devlist gen-devlist
gen_crc32table gen_crc32table
gen_init_cpio gen_init_cpio
genheaders
genksyms genksyms
*_gray256.c *_gray256.c
ihex2fw ihex2fw
......
...@@ -85,7 +85,6 @@ parameter is applicable: ...@@ -85,7 +85,6 @@ parameter is applicable:
PPT Parallel port support is enabled. PPT Parallel port support is enabled.
PS2 Appropriate PS/2 support is enabled. PS2 Appropriate PS/2 support is enabled.
RAM RAM disk support is enabled. RAM RAM disk support is enabled.
ROOTPLUG The example Root Plug LSM is enabled.
S390 S390 architecture is enabled. S390 S390 architecture is enabled.
SCSI Appropriate SCSI support is enabled. SCSI Appropriate SCSI support is enabled.
A lot of drivers has their options described inside of 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 ...@@ -2164,15 +2163,6 @@ and is between 256 and 4096 characters. It is defined in the file
Useful for devices that are detected asynchronously Useful for devices that are detected asynchronously
(e.g. USB and MMC devices). (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 rw [KNL] Mount root device read-write on boot
S [KNL] Run init in single mode S [KNL] Run init in single mode
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
enum tpm_const { enum tpm_const {
TPM_MINOR = 224, /* officially assigned */ TPM_MINOR = 224, /* officially assigned */
TPM_BUFSIZE = 2048, TPM_BUFSIZE = 4096,
TPM_NUM_DEVICES = 256, TPM_NUM_DEVICES = 256,
}; };
......
...@@ -257,6 +257,10 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -257,6 +257,10 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
return size; 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) * 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 * 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) ...@@ -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, wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
&chip->vendor.int_queue); &chip->vendor.int_queue);
status = tpm_tis_status(chip); status = tpm_tis_status(chip);
if ((status & TPM_STS_DATA_EXPECT) == 0) { if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) {
rc = -EIO; rc = -EIO;
goto out_err; goto out_err;
} }
...@@ -467,6 +471,10 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, ...@@ -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", "1.2 TPM (device-id 0x%X, rev-id %d)\n",
vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
if (itpm)
dev_info(dev, "Intel iTPM workaround enabled\n");
/* Figure out the capabilities */ /* Figure out the capabilities */
intfcaps = intfcaps =
ioread32(chip->vendor.iobase + ioread32(chip->vendor.iobase +
...@@ -629,6 +637,7 @@ static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = { ...@@ -629,6 +637,7 @@ static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
{"", 0}, /* User Specified */ {"", 0}, /* User Specified */
{"", 0} /* Terminator */ {"", 0} /* Terminator */
}; };
MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl);
static __devexit void tpm_tis_pnp_remove(struct pnp_dev *dev) static __devexit void tpm_tis_pnp_remove(struct pnp_dev *dev)
{ {
......
...@@ -46,7 +46,6 @@ ...@@ -46,7 +46,6 @@
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/security.h> #include <linux/security.h>
#include <linux/ima.h>
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include <linux/tsacct_kern.h> #include <linux/tsacct_kern.h>
#include <linux/cn_proc.h> #include <linux/cn_proc.h>
...@@ -1207,9 +1206,6 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) ...@@ -1207,9 +1206,6 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
struct linux_binfmt *fmt; struct linux_binfmt *fmt;
retval = security_bprm_check(bprm); retval = security_bprm_check(bprm);
if (retval)
return retval;
retval = ima_bprm_check(bprm);
if (retval) if (retval)
return retval; return retval;
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/security.h> #include <linux/security.h>
#include <linux/ima.h>
#include <linux/eventpoll.h> #include <linux/eventpoll.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <linux/mount.h> #include <linux/mount.h>
...@@ -280,7 +279,6 @@ void __fput(struct file *file) ...@@ -280,7 +279,6 @@ void __fput(struct file *file)
if (file->f_op && file->f_op->release) if (file->f_op && file->f_op->release)
file->f_op->release(inode, file); file->f_op->release(inode, file);
security_file_free(file); security_file_free(file);
ima_file_free(file);
if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL)) if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL))
cdev_put(inode->i_cdev); cdev_put(inode->i_cdev);
fops_put(file->f_op); fops_put(file->f_op);
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include <linux/hash.h> #include <linux/hash.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/security.h> #include <linux/security.h>
#include <linux/ima.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/cdev.h> #include <linux/cdev.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
...@@ -157,11 +156,6 @@ int inode_init_always(struct super_block *sb, struct inode *inode) ...@@ -157,11 +156,6 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
if (security_inode_alloc(inode)) if (security_inode_alloc(inode))
goto out; goto out;
/* allocate and initialize an i_integrity */
if (ima_inode_alloc(inode))
goto out_free_security;
spin_lock_init(&inode->i_lock); spin_lock_init(&inode->i_lock);
lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key); 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) ...@@ -201,9 +195,6 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
#endif #endif
return 0; return 0;
out_free_security:
security_inode_free(inode);
out: out:
return -ENOMEM; return -ENOMEM;
} }
...@@ -235,7 +226,6 @@ static struct inode *alloc_inode(struct super_block *sb) ...@@ -235,7 +226,6 @@ static struct inode *alloc_inode(struct super_block *sb)
void __destroy_inode(struct inode *inode) void __destroy_inode(struct inode *inode)
{ {
BUG_ON(inode_has_buffers(inode)); BUG_ON(inode_has_buffers(inode));
ima_inode_free(inode);
security_inode_free(inode); security_inode_free(inode);
fsnotify_inode_delete(inode); fsnotify_inode_delete(inode);
#ifdef CONFIG_FS_POSIX_ACL #ifdef CONFIG_FS_POSIX_ACL
......
...@@ -1921,6 +1921,16 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, ...@@ -1921,6 +1921,16 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
if (data_page) if (data_page)
((char *)data_page)[PAGE_SIZE - 1] = 0; ((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 */ /* Default to relatime unless overriden */
if (!(flags & MS_NOATIME)) if (!(flags & MS_NOATIME))
mnt_flags |= MNT_RELATIME; mnt_flags |= MNT_RELATIME;
...@@ -1945,16 +1955,6 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, ...@@ -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_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
MS_STRICTATIME); 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) if (flags & MS_REMOUNT)
retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags, retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,
data_page); data_page);
......
...@@ -587,6 +587,9 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename) ...@@ -587,6 +587,9 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename)
error = -EPERM; error = -EPERM;
if (!capable(CAP_SYS_CHROOT)) if (!capable(CAP_SYS_CHROOT))
goto dput_and_out; goto dput_and_out;
error = security_path_chroot(&path);
if (error)
goto dput_and_out;
set_fs_root(current->fs, &path); set_fs_root(current->fs, &path);
error = 0; error = 0;
...@@ -617,11 +620,15 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode) ...@@ -617,11 +620,15 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode)
if (err) if (err)
goto out_putf; goto out_putf;
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
err = security_path_chmod(dentry, file->f_vfsmnt, mode);
if (err)
goto out_unlock;
if (mode == (mode_t) -1) if (mode == (mode_t) -1)
mode = inode->i_mode; mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
err = notify_change(dentry, &newattrs); err = notify_change(dentry, &newattrs);
out_unlock:
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
mnt_drop_write(file->f_path.mnt); mnt_drop_write(file->f_path.mnt);
out_putf: out_putf:
...@@ -646,11 +653,15 @@ SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode) ...@@ -646,11 +653,15 @@ SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode)
if (error) if (error)
goto dput_and_out; goto dput_and_out;
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
error = security_path_chmod(path.dentry, path.mnt, mode);
if (error)
goto out_unlock;
if (mode == (mode_t) -1) if (mode == (mode_t) -1)
mode = inode->i_mode; mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
error = notify_change(path.dentry, &newattrs); error = notify_change(path.dentry, &newattrs);
out_unlock:
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
mnt_drop_write(path.mnt); mnt_drop_write(path.mnt);
dput_and_out: dput_and_out:
...@@ -664,9 +675,9 @@ SYSCALL_DEFINE2(chmod, const char __user *, filename, mode_t, mode) ...@@ -664,9 +675,9 @@ SYSCALL_DEFINE2(chmod, const char __user *, filename, mode_t, mode)
return sys_fchmodat(AT_FDCWD, filename, 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; int error;
struct iattr newattrs; struct iattr newattrs;
...@@ -683,7 +694,9 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group) ...@@ -683,7 +694,9 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
newattrs.ia_valid |= newattrs.ia_valid |=
ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
mutex_lock(&inode->i_mutex); 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); mutex_unlock(&inode->i_mutex);
return error; return error;
...@@ -700,7 +713,7 @@ SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group) ...@@ -700,7 +713,7 @@ SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group)
error = mnt_want_write(path.mnt); error = mnt_want_write(path.mnt);
if (error) if (error)
goto out_release; goto out_release;
error = chown_common(path.dentry, user, group); error = chown_common(&path, user, group);
mnt_drop_write(path.mnt); mnt_drop_write(path.mnt);
out_release: out_release:
path_put(&path); path_put(&path);
...@@ -725,7 +738,7 @@ SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user, ...@@ -725,7 +738,7 @@ SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user,
error = mnt_want_write(path.mnt); error = mnt_want_write(path.mnt);
if (error) if (error)
goto out_release; goto out_release;
error = chown_common(path.dentry, user, group); error = chown_common(&path, user, group);
mnt_drop_write(path.mnt); mnt_drop_write(path.mnt);
out_release: out_release:
path_put(&path); path_put(&path);
...@@ -744,7 +757,7 @@ SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group ...@@ -744,7 +757,7 @@ SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group
error = mnt_want_write(path.mnt); error = mnt_want_write(path.mnt);
if (error) if (error)
goto out_release; goto out_release;
error = chown_common(path.dentry, user, group); error = chown_common(&path, user, group);
mnt_drop_write(path.mnt); mnt_drop_write(path.mnt);
out_release: out_release:
path_put(&path); path_put(&path);
...@@ -767,7 +780,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group) ...@@ -767,7 +780,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
goto out_fput; goto out_fput;
dentry = file->f_path.dentry; dentry = file->f_path.dentry;
audit_inode(NULL, 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); mnt_drop_write(file->f_path.mnt);
out_fput: out_fput:
fput(file); fput(file);
......
...@@ -330,6 +330,7 @@ unifdef-y += scc.h ...@@ -330,6 +330,7 @@ unifdef-y += scc.h
unifdef-y += sched.h unifdef-y += sched.h
unifdef-y += screen_info.h unifdef-y += screen_info.h
unifdef-y += sdla.h unifdef-y += sdla.h
unifdef-y += securebits.h
unifdef-y += selinux_netlink.h unifdef-y += selinux_netlink.h
unifdef-y += sem.h unifdef-y += sem.h
unifdef-y += serial_core.h unifdef-y += serial_core.h
......
...@@ -92,9 +92,7 @@ struct vfs_cap_data { ...@@ -92,9 +92,7 @@ struct vfs_cap_data {
#define _KERNEL_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_3 #define _KERNEL_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_3
#define _KERNEL_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_3 #define _KERNEL_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_3
#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
extern int file_caps_enabled; extern int file_caps_enabled;
#endif
typedef struct kernel_cap_struct { typedef struct kernel_cap_struct {
__u32 cap[_KERNEL_CAPABILITY_U32S]; __u32 cap[_KERNEL_CAPABILITY_U32S];
......
...@@ -83,16 +83,12 @@ extern struct group_info init_groups; ...@@ -83,16 +83,12 @@ extern struct group_info init_groups;
#define INIT_IDS #define INIT_IDS
#endif #endif
#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
/* /*
* Because of the reduced scope of CAP_SETPCAP when filesystem * Because of the reduced scope of CAP_SETPCAP when filesystem
* capabilities are in effect, it is safe to allow CAP_SETPCAP to * capabilities are in effect, it is safe to allow CAP_SETPCAP to
* be available in the default configuration. * be available in the default configuration.
*/ */
# define CAP_INIT_BSET CAP_FULL_SET # define CAP_INIT_BSET CAP_FULL_SET
#else
# define CAP_INIT_BSET CAP_INIT_EFF_SET
#endif
#ifdef CONFIG_TREE_PREEMPT_RCU #ifdef CONFIG_TREE_PREEMPT_RCU
#define INIT_TASK_RCU_PREEMPT(tsk) \ #define INIT_TASK_RCU_PREEMPT(tsk) \
......
...@@ -34,6 +34,7 @@ struct common_audit_data { ...@@ -34,6 +34,7 @@ struct common_audit_data {
#define LSM_AUDIT_DATA_TASK 5 #define LSM_AUDIT_DATA_TASK 5
#define LSM_AUDIT_DATA_KEY 6 #define LSM_AUDIT_DATA_KEY 6
#define LSM_AUDIT_NO_AUDIT 7 #define LSM_AUDIT_NO_AUDIT 7
#define LSM_AUDIT_DATA_KMOD 8
struct task_struct *tsk; struct task_struct *tsk;
union { union {
struct { struct {
...@@ -66,6 +67,7 @@ struct common_audit_data { ...@@ -66,6 +67,7 @@ struct common_audit_data {
char *key_desc; char *key_desc;
} key_struct; } key_struct;
#endif #endif
char *kmod_name;
} u; } u;
/* this union contains LSM specific data */ /* this union contains LSM specific data */
union { union {
......
#ifndef _LINUX_SECUREBITS_H #ifndef _LINUX_SECUREBITS_H
#define _LINUX_SECUREBITS_H 1 #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 #define SECUREBITS_DEFAULT 0x00000000
/* When set UID 0 has no special privileges. When unset, we support /* When set UID 0 has no special privileges. When unset, we support
...@@ -12,6 +21,9 @@ ...@@ -12,6 +21,9 @@
#define SECURE_NOROOT 0 #define SECURE_NOROOT 0
#define SECURE_NOROOT_LOCKED 1 /* make bit-0 immutable */ #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 set, setuid to/from uid 0 does not trigger capability-"fixup".
When unset, to provide compatiblility with old programs relying on When unset, to provide compatiblility with old programs relying on
set*uid to gain/lose privilege, transitions to/from uid 0 cause set*uid to gain/lose privilege, transitions to/from uid 0 cause
...@@ -19,6 +31,10 @@ ...@@ -19,6 +31,10 @@
#define SECURE_NO_SETUID_FIXUP 2 #define SECURE_NO_SETUID_FIXUP 2
#define SECURE_NO_SETUID_FIXUP_LOCKED 3 /* make bit-2 immutable */ #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 /* When set, a process can retain its capabilities even after
transitioning to a non-root user (the set-uid fixup suppressed by 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 bit 2). Bit-4 is cleared when a process calls exec(); setting both
...@@ -27,12 +43,8 @@ ...@@ -27,12 +43,8 @@
#define SECURE_KEEP_CAPS 4 #define SECURE_KEEP_CAPS 4
#define SECURE_KEEP_CAPS_LOCKED 5 /* make bit-4 immutable */ #define SECURE_KEEP_CAPS_LOCKED 5 /* make bit-4 immutable */
/* Each securesetting is implemented using two bits. One bit specifies #define SECBIT_KEEP_CAPS (issecure_mask(SECURE_KEEP_CAPS))
whether the setting is on or off. The other bit specify whether the #define SECBIT_KEEP_CAPS_LOCKED (issecure_mask(SECURE_KEEP_CAPS_LOCKED))
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 SECURE_ALL_BITS (issecure_mask(SECURE_NOROOT) | \ #define SECURE_ALL_BITS (issecure_mask(SECURE_NOROOT) | \
issecure_mask(SECURE_NO_SETUID_FIXUP) | \ issecure_mask(SECURE_NO_SETUID_FIXUP) | \
......
...@@ -447,6 +447,22 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) ...@@ -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_dir contains the path structure for parent of the new link.
* @new_dentry contains the dentry structure of the new link. * @new_dentry contains the dentry structure of the new link.
* Return 0 if permission is granted. * 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: * @inode_readlink:
* Check the permission to read the symbolic link. * Check the permission to read the symbolic link.
* @dentry contains the dentry structure for the file 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) ...@@ -690,6 +706,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* @kernel_module_request: * @kernel_module_request:
* Ability to trigger the kernel to automatically upcall to userspace for * Ability to trigger the kernel to automatically upcall to userspace for
* userspace to load a kernel module with the given name. * userspace to load a kernel module with the given name.
* @kmod_name name of the module requested by the kernel
* Return 0 if successful. * Return 0 if successful.
* @task_setuid: * @task_setuid:
* Check permission before setting one or more of the user identity * Check permission before setting one or more of the user identity
...@@ -1488,6 +1505,10 @@ struct security_operations { ...@@ -1488,6 +1505,10 @@ struct security_operations {
struct dentry *new_dentry); struct dentry *new_dentry);
int (*path_rename) (struct path *old_dir, struct dentry *old_dentry, int (*path_rename) (struct path *old_dir, struct dentry *old_dentry,
struct path *new_dir, struct dentry *new_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 #endif
int (*inode_alloc_security) (struct inode *inode); int (*inode_alloc_security) (struct inode *inode);
...@@ -1557,7 +1578,7 @@ struct security_operations { ...@@ -1557,7 +1578,7 @@ struct security_operations {
void (*cred_transfer)(struct cred *new, const struct cred *old); void (*cred_transfer)(struct cred *new, const struct cred *old);
int (*kernel_act_as)(struct cred *new, u32 secid); int (*kernel_act_as)(struct cred *new, u32 secid);
int (*kernel_create_files_as)(struct cred *new, struct inode *inode); 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_setuid) (uid_t id0, uid_t id1, uid_t id2, int flags);
int (*task_fix_setuid) (struct cred *new, const struct cred *old, int (*task_fix_setuid) (struct cred *new, const struct cred *old,
int flags); int flags);
...@@ -1822,7 +1843,7 @@ void security_commit_creds(struct cred *new, const struct cred *old); ...@@ -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); void security_transfer_creds(struct cred *new, const struct cred *old);
int security_kernel_act_as(struct cred *new, u32 secid); 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_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_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 security_task_fix_setuid(struct cred *new, const struct cred *old,
int flags); int flags);
...@@ -2387,7 +2408,7 @@ static inline int security_kernel_create_files_as(struct cred *cred, ...@@ -2387,7 +2408,7 @@ static inline int security_kernel_create_files_as(struct cred *cred,
return 0; return 0;
} }
static inline int security_kernel_module_request(void) static inline int security_kernel_module_request(char *kmod_name)
{ {
return 0; return 0;
} }
...@@ -2952,6 +2973,10 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir, ...@@ -2952,6 +2973,10 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
struct dentry *new_dentry); struct dentry *new_dentry);
int security_path_rename(struct path *old_dir, struct dentry *old_dentry, int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
struct path *new_dir, struct dentry *new_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 */ #else /* CONFIG_SECURITY_PATH */
static inline int security_path_unlink(struct path *dir, struct dentry *dentry) 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, ...@@ -3001,6 +3026,23 @@ static inline int security_path_rename(struct path *old_dir,
{ {
return 0; 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 */ #endif /* CONFIG_SECURITY_PATH */
#ifdef CONFIG_KEYS #ifdef CONFIG_KEYS
......
...@@ -27,9 +27,16 @@ ...@@ -27,9 +27,16 @@
*/ */
#define TPM_ANY_NUM 0xFFFF #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_read(u32 chip_num, int pcr_idx, u8 *res_buf);
extern int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash); 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
#endif #endif
...@@ -29,7 +29,6 @@ EXPORT_SYMBOL(__cap_empty_set); ...@@ -29,7 +29,6 @@ EXPORT_SYMBOL(__cap_empty_set);
EXPORT_SYMBOL(__cap_full_set); EXPORT_SYMBOL(__cap_full_set);
EXPORT_SYMBOL(__cap_init_eff_set); EXPORT_SYMBOL(__cap_init_eff_set);
#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
int file_caps_enabled = 1; int file_caps_enabled = 1;
static int __init file_caps_disable(char *str) static int __init file_caps_disable(char *str)
...@@ -38,7 +37,6 @@ static int __init file_caps_disable(char *str) ...@@ -38,7 +37,6 @@ static int __init file_caps_disable(char *str)
return 1; return 1;
} }
__setup("no_file_caps", file_caps_disable); __setup("no_file_caps", file_caps_disable);
#endif
/* /*
* More recent versions of libcap are available from: * 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) ...@@ -169,8 +167,8 @@ SYSCALL_DEFINE2(capget, cap_user_header_t, header, cap_user_data_t, dataptr)
kernel_cap_t pE, pI, pP; kernel_cap_t pE, pI, pP;
ret = cap_validate_magic(header, &tocopy); ret = cap_validate_magic(header, &tocopy);
if (ret != 0) if ((dataptr == NULL) || (ret != 0))
return ret; return ((dataptr == NULL) && (ret == -EINVAL)) ? 0 : ret;
if (get_user(pid, &header->pid)) if (get_user(pid, &header->pid))
return -EFAULT; return -EFAULT;
...@@ -238,7 +236,7 @@ SYSCALL_DEFINE2(capget, cap_user_header_t, header, cap_user_data_t, dataptr) ...@@ -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) SYSCALL_DEFINE2(capset, cap_user_header_t, header, const cap_user_data_t, data)
{ {
struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S]; struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S];
unsigned i, tocopy; unsigned i, tocopy, copybytes;
kernel_cap_t inheritable, permitted, effective; kernel_cap_t inheritable, permitted, effective;
struct cred *new; struct cred *new;
int ret; int ret;
...@@ -255,8 +253,11 @@ SYSCALL_DEFINE2(capset, cap_user_header_t, header, const cap_user_data_t, data) ...@@ -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)) if (pid != 0 && pid != task_pid_vnr(current))
return -EPERM; return -EPERM;
if (copy_from_user(&kdata, data, copybytes = tocopy * sizeof(struct __user_cap_data_struct);
tocopy * sizeof(struct __user_cap_data_struct))) if (copybytes > sizeof(kdata))
return -EFAULT;
if (copy_from_user(&kdata, data, copybytes))
return -EFAULT; return -EFAULT;
for (i = 0; i < tocopy; i++) { for (i = 0; i < tocopy; i++) {
......
...@@ -80,16 +80,16 @@ int __request_module(bool wait, const char *fmt, ...) ...@@ -80,16 +80,16 @@ int __request_module(bool wait, const char *fmt, ...)
#define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */ #define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */
static int kmod_loop_msg; static int kmod_loop_msg;
ret = security_kernel_module_request();
if (ret)
return ret;
va_start(args, fmt); va_start(args, fmt);
ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args); ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);
va_end(args); va_end(args);
if (ret >= MODULE_NAME_LEN) if (ret >= MODULE_NAME_LEN)
return -ENAMETOOLONG; 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 /* 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 * loop. Limit the number of running kmod threads to max_threads/2 or
* MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method * MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/personality.h> #include <linux/personality.h>
#include <linux/security.h> #include <linux/security.h>
#include <linux/ima.h>
#include <linux/hugetlb.h> #include <linux/hugetlb.h>
#include <linux/profile.h> #include <linux/profile.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -1059,9 +1058,6 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, ...@@ -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); error = security_file_mmap(file, reqprot, prot, flags, addr, 0);
if (error)
return error;
error = ima_file_mmap(file, prot);
if (error) if (error)
return error; return error;
......
subdir-y := mdp subdir-y := mdp genheaders
subdir- += mdp 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 @@ ...@@ -29,86 +29,27 @@
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include "flask.h"
static void usage(char *name) static void usage(char *name)
{ {
printf("usage: %s [-m] policy_file context_file\n", name); printf("usage: %s [-m] policy_file context_file\n", name);
exit(1); exit(1);
} }
static void find_common_name(char *cname, char *dest, int len) /* Class/perm mapping support */
{ struct security_class_mapping {
char *start, *end; const char *name;
const char *perms[sizeof(unsigned) * 8 + 1];
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
}; };
#undef S_
#include "classmap.h"
#include "initial_sid_to_string.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 main(int argc, char *argv[])
{ {
int i, j, mls = 0; int i, j, mls = 0;
int initial_sid_to_string_len;
char **arg, *polout, *ctxout; char **arg, *polout, *ctxout;
int classlist_len, initial_sid_to_string_len;
FILE *fout; FILE *fout;
if (argc < 3) if (argc < 3)
...@@ -127,65 +68,26 @@ int main(int argc, char *argv[]) ...@@ -127,65 +68,26 @@ int main(int argc, char *argv[])
usage(argv[0]); usage(argv[0]);
} }
classlist_len = sizeof(classlist) / sizeof(char *);
/* print out the classes */ /* print out the classes */
for (i=1; i < classlist_len; i++) { for (i = 0; secclass_map[i].name; i++)
if(classlist[i]) fprintf(fout, "class %s\n", secclass_map[i].name);
fprintf(fout, "class %s\n", classlist[i]);
else
fprintf(fout, "class user%d\n", i);
}
fprintf(fout, "\n"); fprintf(fout, "\n");
initial_sid_to_string_len = sizeof(initial_sid_to_string) / sizeof (char *); initial_sid_to_string_len = sizeof(initial_sid_to_string) / sizeof (char *);
/* print out the sids */ /* 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, "sid %s\n", initial_sid_to_string[i]);
fprintf(fout, "\n"); 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 */ /* print out the class permissions */
for (i=1; i < classlist_len; i++) { for (i = 0; secclass_map[i].name; i++) {
if (classlist[i]) { struct security_class_mapping *map = &secclass_map[i];
int firstperm = -1, numperms = 0; fprintf(fout, "class %s\n", map->name);
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;
}
fprintf(fout, "{\n"); fprintf(fout, "{\n");
/* print out the av_perms */ for (j = 0; map->perms[j]; j++)
for (j=0; j < numperms; j++) { fprintf(fout, "\t%s\n", map->perms[j]);
fprintf(fout, "\t%s\n", av_perms[firstperm+j].perm_s);
}
fprintf(fout, "}\n\n"); fprintf(fout, "}\n\n");
} }
}
fprintf(fout, "\n"); fprintf(fout, "\n");
/* NOW PRINT OUT MLS STUFF */ /* NOW PRINT OUT MLS STUFF */
...@@ -197,31 +99,34 @@ int main(int argc, char *argv[]) ...@@ -197,31 +99,34 @@ int main(int argc, char *argv[])
/* types, roles, and allows */ /* types, roles, and allows */
fprintf(fout, "type base_t;\n"); fprintf(fout, "type base_t;\n");
fprintf(fout, "role base_r types { base_t };\n"); fprintf(fout, "role base_r types { base_t };\n");
for (i=1; i < classlist_len; i++) { for (i = 0; secclass_map[i].name; i++)
if (classlist[i]) fprintf(fout, "allow base_t base_t:%s *;\n",
fprintf(fout, "allow base_t base_t:%s *;\n", classlist[i]); secclass_map[i].name);
else
fprintf(fout, "allow base_t base_t:user%d *;\n", i);
}
fprintf(fout, "user user_u roles { base_r };\n"); fprintf(fout, "user user_u roles { base_r };\n");
fprintf(fout, "\n"); fprintf(fout, "\n");
/* default sids */ /* 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, "sid %s user_u:base_r:base_t\n", initial_sid_to_string[i]);
fprintf(fout, "\n"); fprintf(fout, "\n");
fprintf(fout, "fs_use_xattr ext2 user_u:base_r:base_t;\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 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 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 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 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 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_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 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 tmpfs user_u:base_r:base_t;\n");
fprintf(fout, "fs_use_trans shm 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 ...@@ -91,28 +91,6 @@ config SECURITY_PATH
implement pathname based access controls. implement pathname based access controls.
If you are unsure how to answer this question, answer N. 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 config INTEL_TXT
bool "Enable Intel(R) Trusted Execution Technology (Intel(R) TXT)" bool "Enable Intel(R) Trusted Execution Technology (Intel(R) TXT)"
depends on HAVE_INTEL_TXT depends on HAVE_INTEL_TXT
...@@ -165,5 +143,37 @@ source security/tomoyo/Kconfig ...@@ -165,5 +143,37 @@ source security/tomoyo/Kconfig
source security/integrity/ima/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 endmenu
...@@ -18,7 +18,6 @@ obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o ...@@ -18,7 +18,6 @@ obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
obj-$(CONFIG_AUDIT) += lsm_audit.o obj-$(CONFIG_AUDIT) += lsm_audit.o
obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o
obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o
obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
# Object integrity file lists # Object integrity file lists
......
...@@ -308,6 +308,22 @@ static int cap_path_truncate(struct path *path, loff_t length, ...@@ -308,6 +308,22 @@ static int cap_path_truncate(struct path *path, loff_t length,
{ {
return 0; 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 #endif
static int cap_file_permission(struct file *file, int mask) 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) ...@@ -405,7 +421,7 @@ static int cap_kernel_create_files_as(struct cred *new, struct inode *inode)
return 0; return 0;
} }
static int cap_kernel_module_request(void) static int cap_kernel_module_request(char *kmod_name)
{ {
return 0; return 0;
} }
...@@ -977,6 +993,9 @@ void security_fixup_ops(struct security_operations *ops) ...@@ -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_link);
set_to_cap_if_null(ops, path_rename); set_to_cap_if_null(ops, path_rename);
set_to_cap_if_null(ops, path_truncate); 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 #endif
set_to_cap_if_null(ops, file_permission); set_to_cap_if_null(ops, file_permission);
set_to_cap_if_null(ops, file_alloc_security); 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 * 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 * 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, ...@@ -173,7 +173,6 @@ int cap_capget(struct task_struct *target, kernel_cap_t *effective,
*/ */
static inline int cap_inh_is_capped(void) 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 /* they are so limited unless the current task has the CAP_SETPCAP
* capability * capability
...@@ -181,7 +180,6 @@ static inline int cap_inh_is_capped(void) ...@@ -181,7 +180,6 @@ static inline int cap_inh_is_capped(void)
if (cap_capable(current, current_cred(), CAP_SETPCAP, if (cap_capable(current, current_cred(), CAP_SETPCAP,
SECURITY_CAP_AUDIT) == 0) SECURITY_CAP_AUDIT) == 0)
return 0; return 0;
#endif
return 1; return 1;
} }
...@@ -239,8 +237,6 @@ static inline void bprm_clear_caps(struct linux_binprm *bprm) ...@@ -239,8 +237,6 @@ static inline void bprm_clear_caps(struct linux_binprm *bprm)
bprm->cap_effective = false; bprm->cap_effective = false;
} }
#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
/** /**
* cap_inode_need_killpriv - Determine if inode change affects privileges * cap_inode_need_killpriv - Determine if inode change affects privileges
* @dentry: The inode/dentry in being changed with change marked ATTR_KILL_PRIV * @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) ...@@ -421,49 +417,6 @@ static int get_file_caps(struct linux_binprm *bprm, bool *effective)
return rc; 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(). * cap_bprm_set_creds - Set up the proposed credentials for execve().
* @bprm: The execution parameters, including the proposed creds * @bprm: The execution parameters, including the proposed creds
...@@ -523,7 +476,6 @@ int cap_bprm_set_creds(struct linux_binprm *bprm) ...@@ -523,7 +476,6 @@ int cap_bprm_set_creds(struct linux_binprm *bprm)
new->euid = new->uid; new->euid = new->uid;
new->egid = new->gid; new->egid = new->gid;
} }
if (cap_limit_ptraced_target())
new->cap_permitted = cap_intersect(new->cap_permitted, new->cap_permitted = cap_intersect(new->cap_permitted,
old->cap_permitted); old->cap_permitted);
} }
...@@ -739,7 +691,6 @@ int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags) ...@@ -739,7 +691,6 @@ int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags)
return 0; return 0;
} }
#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
/* /*
* Rationale: code calling task_setscheduler, task_setioprio, and * Rationale: code calling task_setscheduler, task_setioprio, and
* task_setnice, assumes that * task_setnice, assumes that
...@@ -820,22 +771,6 @@ static long cap_prctl_drop(struct cred *new, unsigned long cap) ...@@ -820,22 +771,6 @@ static long cap_prctl_drop(struct cred *new, unsigned long cap)
return 0; 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 * cap_task_prctl - Implement process control functions for this security module
* @option: The process control function requested * @option: The process control function requested
...@@ -866,7 +801,6 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, ...@@ -866,7 +801,6 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
error = !!cap_raised(new->cap_bset, arg2); error = !!cap_raised(new->cap_bset, arg2);
goto no_change; goto no_change;
#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
case PR_CAPBSET_DROP: case PR_CAPBSET_DROP:
error = cap_prctl_drop(new, arg2); error = cap_prctl_drop(new, arg2);
if (error < 0) if (error < 0)
...@@ -917,8 +851,6 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, ...@@ -917,8 +851,6 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
error = new->securebits; error = new->securebits;
goto no_change; goto no_change;
#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */
case PR_GET_KEEPCAPS: case PR_GET_KEEPCAPS:
if (issecure(SECURE_KEEP_CAPS)) if (issecure(SECURE_KEEP_CAPS))
error = 1; error = 1;
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
config IMA config IMA
bool "Integrity Measurement Architecture(IMA)" bool "Integrity Measurement Architecture(IMA)"
depends on ACPI depends on ACPI
depends on SECURITY
select SECURITYFS select SECURITYFS
select CRYPTO select CRYPTO
select CRYPTO_HMAC select CRYPTO_HMAC
......
...@@ -354,6 +354,10 @@ static void dump_common_audit_data(struct audit_buffer *ab, ...@@ -354,6 +354,10 @@ static void dump_common_audit_data(struct audit_buffer *ab,
} }
break; break;
#endif #endif
case LSM_AUDIT_DATA_KMOD:
audit_log_format(ab, " kmod=");
audit_log_untrustedstring(ab, a->u.kmod_name);
break;
} /* switch (a->type) */ } /* switch (a->type) */
} }
......
...@@ -33,6 +33,9 @@ int mmap_min_addr_handler(struct ctl_table *table, int write, ...@@ -33,6 +33,9 @@ int mmap_min_addr_handler(struct ctl_table *table, int write,
{ {
int ret; int ret;
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos); ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
update_mmap_min_addr(); 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 @@ ...@@ -16,9 +16,11 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/security.h> #include <linux/security.h>
#include <linux/ima.h>
/* Boot-time LSM user choice */ /* 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 */ /* things that live in capability.c */
extern struct security_operations default_security_ops; extern struct security_operations default_security_ops;
...@@ -79,8 +81,10 @@ __setup("security=", choose_lsm); ...@@ -79,8 +81,10 @@ __setup("security=", choose_lsm);
* *
* Return true if: * Return true if:
* -The passed LSM is the one chosen by user at boot time, * -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 * -or the passed LSM is configured as the default and the user did not
* for registration permission, * 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. * -or the passed LSM is currently loaded.
* Otherwise, return false. * Otherwise, return false.
*/ */
...@@ -235,7 +239,12 @@ int security_bprm_set_creds(struct linux_binprm *bprm) ...@@ -235,7 +239,12 @@ int security_bprm_set_creds(struct linux_binprm *bprm)
int security_bprm_check(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) void security_bprm_committing_creds(struct linux_binprm *bprm)
...@@ -352,12 +361,21 @@ EXPORT_SYMBOL(security_sb_parse_opts_str); ...@@ -352,12 +361,21 @@ EXPORT_SYMBOL(security_sb_parse_opts_str);
int security_inode_alloc(struct inode *inode) int security_inode_alloc(struct inode *inode)
{ {
int ret;
inode->i_security = NULL; 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) void security_inode_free(struct inode *inode)
{ {
ima_inode_free(inode);
security_ops->inode_free_security(inode); security_ops->inode_free_security(inode);
} }
...@@ -434,6 +452,26 @@ int security_path_truncate(struct path *path, loff_t length, ...@@ -434,6 +452,26 @@ int security_path_truncate(struct path *path, loff_t length,
return 0; return 0;
return security_ops->path_truncate(path, length, time_attrs); 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 #endif
int security_inode_create(struct inode *dir, struct dentry *dentry, int mode) int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
...@@ -628,6 +666,8 @@ int security_file_alloc(struct file *file) ...@@ -628,6 +666,8 @@ int security_file_alloc(struct file *file)
void security_file_free(struct file *file) void security_file_free(struct file *file)
{ {
security_ops->file_free_security(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) 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, ...@@ -639,7 +679,12 @@ int security_file_mmap(struct file *file, unsigned long reqprot,
unsigned long prot, unsigned long flags, unsigned long prot, unsigned long flags,
unsigned long addr, unsigned long addr_only) 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, 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) ...@@ -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); 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) 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 ...@@ -18,5 +18,13 @@ selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
selinux-$(CONFIG_NETLABEL) += netlabel.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 @@ ...@@ -31,43 +31,7 @@
#include <net/ipv6.h> #include <net/ipv6.h>
#include "avc.h" #include "avc.h"
#include "avc_ss.h" #include "avc_ss.h"
#include "classmap.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)
};
#define AVC_CACHE_SLOTS 512 #define AVC_CACHE_SLOTS 512
#define AVC_DEF_CACHE_THRESHOLD 512 #define AVC_DEF_CACHE_THRESHOLD 512
...@@ -139,48 +103,24 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass) ...@@ -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) static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
{ {
const char **common_pts = NULL; const char **perms;
u32 common_base = 0; int i, perm;
int i, i2, perm;
if (av == 0) { if (av == 0) {
audit_log_format(ab, " null"); audit_log_format(ab, " null");
return; return;
} }
for (i = 0; i < ARRAY_SIZE(av_inherit); i++) { perms = secclass_map[tclass-1].perms;
if (av_inherit[i].tclass == tclass) {
common_pts = av_inherit[i].common_pts;
common_base = av_inherit[i].common_base;
break;
}
}
audit_log_format(ab, " {"); audit_log_format(ab, " {");
i = 0; i = 0;
perm = 1; perm = 1;
while (perm < common_base) { while (i < (sizeof(av) * 8)) {
if (perm & av) { if ((perm & av) && perms[i]) {
audit_log_format(ab, " %s", common_pts[i]); audit_log_format(ab, " %s", perms[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);
av &= ~perm; av &= ~perm;
} }
}
i++; i++;
perm <<= 1; perm <<= 1;
} }
...@@ -219,8 +159,8 @@ static void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tcla ...@@ -219,8 +159,8 @@ static void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tcla
kfree(scontext); kfree(scontext);
} }
BUG_ON(tclass >= ARRAY_SIZE(class_to_string) || !class_to_string[tclass]); BUG_ON(tclass >= ARRAY_SIZE(secclass_map));
audit_log_format(ab, " tclass=%s", class_to_string[tclass]); audit_log_format(ab, " tclass=%s", secclass_map[tclass-1].name);
} }
/** /**
......
...@@ -91,7 +91,6 @@ ...@@ -91,7 +91,6 @@
#define NUM_SEL_MNT_OPTS 5 #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 int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
extern struct security_operations *security_ops; extern struct security_operations *security_ops;
...@@ -3338,9 +3337,18 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) ...@@ -3338,9 +3337,18 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
return 0; 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) 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) ...@@ -4714,10 +4722,7 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
if (err) if (err)
return err; return err;
if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS) return selinux_nlmsg_perm(sk, skb);
err = selinux_nlmsg_perm(sk, skb);
return err;
} }
static int selinux_netlink_recv(struct sk_buff *skb, int capability) static int selinux_netlink_recv(struct sk_buff *skb, int capability)
...@@ -5830,12 +5835,12 @@ int selinux_disable(void) ...@@ -5830,12 +5835,12 @@ int selinux_disable(void)
selinux_disabled = 1; selinux_disabled = 1;
selinux_enabled = 0; selinux_enabled = 0;
/* Try to destroy the avc node cache */
avc_disable();
/* Reset security_ops to the secondary module, dummy or capability. */ /* Reset security_ops to the secondary module, dummy or capability. */
security_ops = secondary_ops; security_ops = secondary_ops;
/* Try to destroy the avc node cache */
avc_disable();
/* Unregister netfilter hooks. */ /* Unregister netfilter hooks. */
selinux_nf_ip_exit(); 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 @@ ...@@ -10,26 +10,13 @@
int avc_ss_reset(u32 seqno); int avc_ss_reset(u32 seqno);
struct av_perm_to_string { /* Class/perm mapping support */
u16 tclass; struct security_class_mapping {
u32 value;
const char *name; const char *name;
const char *perms[sizeof(u32) * 8 + 1];
}; };
struct av_inherit { extern struct security_class_mapping secclass_map[];
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;
};
#endif /* _SELINUX_AVC_SS_H_ */ #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, ...@@ -100,9 +100,16 @@ int security_compute_av(u32 ssid, u32 tsid,
u16 tclass, u32 requested, u16 tclass, u32 requested,
struct av_decision *avd); 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, int security_transition_sid(u32 ssid, u32 tsid,
u16 tclass, u32 *out_sid); 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, int security_member_sid(u32 ssid, u32 tsid,
u16 tclass, u32 *out_sid); u16 tclass, u32 *out_sid);
......
...@@ -522,7 +522,7 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) ...@@ -522,7 +522,7 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size)
if (length < 0) if (length < 0)
goto out2; goto out2;
length = security_compute_av(ssid, tsid, tclass, req, &avd); length = security_compute_av_user(ssid, tsid, tclass, req, &avd);
if (length < 0) if (length < 0)
goto out2; goto out2;
...@@ -571,7 +571,7 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) ...@@ -571,7 +571,7 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
if (length < 0) if (length < 0)
goto out2; goto out2;
length = security_transition_sid(ssid, tsid, tclass, &newsid); length = security_transition_sid_user(ssid, tsid, tclass, &newsid);
if (length < 0) if (length < 0)
goto out2; goto out2;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Makefile for building the SELinux security server as part of the kernel tree. # 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 obj-y := ss.o
ss-y := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o conditional.o mls.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, ...@@ -532,7 +532,7 @@ int mls_compute_sid(struct context *scontext,
} }
/* Fallthrough */ /* Fallthrough */
case AVTAB_CHANGE: case AVTAB_CHANGE:
if (tclass == SECCLASS_PROCESS) if (tclass == policydb.process_class)
/* Use the process MLS attributes. */ /* Use the process MLS attributes. */
return mls_context_cpy(newcontext, scontext); return mls_context_cpy(newcontext, scontext);
else else
......
...@@ -713,7 +713,6 @@ void policydb_destroy(struct policydb *p) ...@@ -713,7 +713,6 @@ void policydb_destroy(struct policydb *p)
ebitmap_destroy(&p->type_attr_map[i]); ebitmap_destroy(&p->type_attr_map[i]);
} }
kfree(p->type_attr_map); kfree(p->type_attr_map);
kfree(p->undefined_perms);
ebitmap_destroy(&p->policycaps); ebitmap_destroy(&p->policycaps);
ebitmap_destroy(&p->permissive_map); ebitmap_destroy(&p->permissive_map);
...@@ -1640,6 +1639,40 @@ static int policydb_bounds_sanity_check(struct policydb *p) ...@@ -1640,6 +1639,40 @@ static int policydb_bounds_sanity_check(struct policydb *p)
extern int ss_initialized; 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 * Read the configuration data from a policy database binary
* representation file into a policy database structure. * representation file into a policy database structure.
...@@ -1861,6 +1894,16 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1861,6 +1894,16 @@ int policydb_read(struct policydb *p, void *fp)
if (rc) if (rc)
goto bad; 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++) { for (i = 0; i < info->ocon_num; i++) {
rc = next_entry(buf, fp, sizeof(u32)); rc = next_entry(buf, fp, sizeof(u32));
if (rc < 0) if (rc < 0)
...@@ -2101,7 +2144,7 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -2101,7 +2144,7 @@ int policydb_read(struct policydb *p, void *fp)
goto bad; goto bad;
rt->target_class = le32_to_cpu(buf[0]); rt->target_class = le32_to_cpu(buf[0]);
} else } else
rt->target_class = SECCLASS_PROCESS; rt->target_class = p->process_class;
if (!policydb_type_isvalid(p, rt->source_type) || if (!policydb_type_isvalid(p, rt->source_type) ||
!policydb_type_isvalid(p, rt->target_type) || !policydb_type_isvalid(p, rt->target_type) ||
!policydb_class_isvalid(p, rt->target_class)) { !policydb_class_isvalid(p, rt->target_class)) {
......
...@@ -254,7 +254,9 @@ struct policydb { ...@@ -254,7 +254,9 @@ struct policydb {
unsigned int reject_unknown : 1; unsigned int reject_unknown : 1;
unsigned int allow_unknown : 1; unsigned int allow_unknown : 1;
u32 *undefined_perms;
u16 process_class;
u32 process_trans_perms;
}; };
extern void policydb_destroy(struct policydb *p); 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) ...@@ -295,5 +297,8 @@ static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes)
return 0; 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_ */ #endif /* _SS_POLICYDB_H_ */
This diff is collapsed.
...@@ -187,6 +187,8 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type, ...@@ -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 s8 pattern_type, const s8 end_type,
const char *function) const char *function)
{ {
const char *const start = filename;
bool in_repetition = false;
bool contains_pattern = false; bool contains_pattern = false;
unsigned char c; unsigned char c;
unsigned char d; unsigned char d;
...@@ -212,9 +214,13 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type, ...@@ -212,9 +214,13 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
if (c == '/') if (c == '/')
goto out; goto out;
} }
while ((c = *filename++) != '\0') { while (1) {
c = *filename++;
if (!c)
break;
if (c == '\\') { if (c == '\\') {
switch ((c = *filename++)) { c = *filename++;
switch (c) {
case '\\': /* "\\" */ case '\\': /* "\\" */
continue; continue;
case '$': /* "\$" */ case '$': /* "\$" */
...@@ -231,6 +237,22 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type, ...@@ -231,6 +237,22 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
break; /* Must not contain pattern */ break; /* Must not contain pattern */
contains_pattern = true; contains_pattern = true;
continue; 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 '0': /* "\ooo" */
case '1': case '1':
case '2': case '2':
...@@ -246,6 +268,8 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type, ...@@ -246,6 +268,8 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
continue; /* pattern is not \000 */ continue; /* pattern is not \000 */
} }
goto out; goto out;
} else if (in_repetition && c == '/') {
goto out;
} else if (tomoyo_is_invalid(c)) { } else if (tomoyo_is_invalid(c)) {
goto out; goto out;
} }
...@@ -254,6 +278,8 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type, ...@@ -254,6 +278,8 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
if (!contains_pattern) if (!contains_pattern)
goto out; goto out;
} }
if (in_repetition)
goto out;
return true; return true;
out: out:
printk(KERN_DEBUG "%s: Invalid pathname '%s'\n", function, printk(KERN_DEBUG "%s: Invalid pathname '%s'\n", function,
...@@ -359,33 +385,6 @@ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname) ...@@ -359,33 +385,6 @@ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
return NULL; 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. * 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) ...@@ -444,11 +443,10 @@ void tomoyo_fill_path_info(struct tomoyo_path_info *ptr)
ptr->is_dir = len && (name[len - 1] == '/'); ptr->is_dir = len && (name[len - 1] == '/');
ptr->is_patterned = (ptr->const_len < len); ptr->is_patterned = (ptr->const_len < len);
ptr->hash = full_name_hash(name, 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. * and "\-" pattern.
* *
* @filename: The start of string to check. * @filename: The start of string to check.
...@@ -458,7 +456,7 @@ void tomoyo_fill_path_info(struct tomoyo_path_info *ptr) ...@@ -458,7 +456,7 @@ void tomoyo_fill_path_info(struct tomoyo_path_info *ptr)
* *
* Returns true if @filename matches @pattern, false otherwise. * 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 *filename_end,
const char *pattern, const char *pattern,
const char *pattern_end) const char *pattern_end)
...@@ -519,7 +517,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename, ...@@ -519,7 +517,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename,
case '*': case '*':
case '@': case '@':
for (i = 0; i <= filename_end - filename; i++) { for (i = 0; i <= filename_end - filename; i++) {
if (tomoyo_file_matches_to_pattern2( if (tomoyo_file_matches_pattern2(
filename + i, filename_end, filename + i, filename_end,
pattern + 1, pattern_end)) pattern + 1, pattern_end))
return true; return true;
...@@ -550,7 +548,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename, ...@@ -550,7 +548,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename,
j++; j++;
} }
for (i = 1; i <= j; i++) { for (i = 1; i <= j; i++) {
if (tomoyo_file_matches_to_pattern2( if (tomoyo_file_matches_pattern2(
filename + i, filename_end, filename + i, filename_end,
pattern + 1, pattern_end)) pattern + 1, pattern_end))
return true; return true;
...@@ -567,7 +565,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename, ...@@ -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: The start of string to check.
* @filename_end: The end 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, ...@@ -576,7 +574,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename,
* *
* Returns true if @filename matches @pattern, false otherwise. * 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 *filename_end,
const char *pattern, const char *pattern,
const char *pattern_end) const char *pattern_end)
...@@ -589,7 +587,7 @@ static bool tomoyo_file_matches_to_pattern(const char *filename, ...@@ -589,7 +587,7 @@ static bool tomoyo_file_matches_to_pattern(const char *filename,
/* Split at "\-" pattern. */ /* Split at "\-" pattern. */
if (*pattern++ != '\\' || *pattern++ != '-') if (*pattern++ != '\\' || *pattern++ != '-')
continue; continue;
result = tomoyo_file_matches_to_pattern2(filename, result = tomoyo_file_matches_pattern2(filename,
filename_end, filename_end,
pattern_start, pattern_start,
pattern - 2); pattern - 2);
...@@ -600,13 +598,79 @@ static bool tomoyo_file_matches_to_pattern(const char *filename, ...@@ -600,13 +598,79 @@ static bool tomoyo_file_matches_to_pattern(const char *filename,
first = false; first = false;
pattern_start = pattern; pattern_start = pattern;
} }
result = tomoyo_file_matches_to_pattern2(filename, filename_end, result = tomoyo_file_matches_pattern2(filename, filename_end,
pattern_start, pattern_end); pattern_start, pattern_end);
return first ? result : !result; 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. * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern.
*
* @filename: The filename to check. * @filename: The filename to check.
* @pattern: The pattern to compare. * @pattern: The pattern to compare.
* *
...@@ -615,24 +679,24 @@ static bool tomoyo_file_matches_to_pattern(const char *filename, ...@@ -615,24 +679,24 @@ static bool tomoyo_file_matches_to_pattern(const char *filename,
* The following patterns are available. * The following patterns are available.
* \\ \ itself. * \\ \ itself.
* \ooo Octal representation of a byte. * \ooo Octal representation of a byte.
* \* More than or equals to 0 character other than '/'. * \* Zero or more repetitions of characters other than '/'.
* \@ More than or equals to 0 character other than '/' or '.'. * \@ Zero or more repetitions of characters other than '/' or '.'.
* \? 1 byte character other than '/'. * \? 1 byte character other than '/'.
* \$ More than or equals to 1 decimal digit. * \$ One or more repetitions of decimal digits.
* \+ 1 decimal digit. * \+ 1 decimal digit.
* \X More than or equals to 1 hexadecimal digit. * \X One or more repetitions of hexadecimal digits.
* \x 1 hexadecimal digit. * \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. * \a 1 alphabet character.
*
* \- Subtraction operator. * \- 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, bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
const struct tomoyo_path_info *pattern) const struct tomoyo_path_info *pattern)
{ {
/*
if (!filename || !pattern)
return false;
*/
const char *f = filename->name; const char *f = filename->name;
const char *p = pattern->name; const char *p = pattern->name;
const int len = pattern->const_len; const int len = pattern->const_len;
...@@ -640,37 +704,15 @@ bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, ...@@ -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 doesn't contain pattern, I can use strcmp(). */
if (!pattern->is_patterned) if (!pattern->is_patterned)
return !tomoyo_pathcmp(filename, pattern); return !tomoyo_pathcmp(filename, pattern);
/* Dont compare if the number of '/' differs. */ /* Don't compare directory and non-directory. */
if (filename->depth != pattern->depth) if (filename->is_dir != pattern->is_dir)
return false; return false;
/* Compare the initial length without patterns. */ /* Compare the initial length without patterns. */
if (strncmp(f, p, len)) if (strncmp(f, p, len))
return false; return false;
f += len; f += len;
p += len; p += len;
/* Main loop. Compare each directory component. */ return tomoyo_path_matches_pattern2(f, p);
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;
} }
/** /**
......
...@@ -56,9 +56,6 @@ struct tomoyo_page_buffer { ...@@ -56,9 +56,6 @@ struct tomoyo_page_buffer {
* (5) "is_patterned" is a bool which is true if "name" contains wildcard * (5) "is_patterned" is a bool which is true if "name" contains wildcard
* characters, false otherwise. This allows TOMOYO to use "hash" and * characters, false otherwise. This allows TOMOYO to use "hash" and
* strcmp() for string comparison if "is_patterned" is false. * 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 { struct tomoyo_path_info {
const char *name; const char *name;
...@@ -66,7 +63,6 @@ struct tomoyo_path_info { ...@@ -66,7 +63,6 @@ struct tomoyo_path_info {
u16 const_len; /* = tomoyo_const_part_length(name) */ u16 const_len; /* = tomoyo_const_part_length(name) */
bool is_dir; /* = tomoyo_strendswith(name, "/") */ bool is_dir; /* = tomoyo_strendswith(name, "/") */
bool is_patterned; /* = tomoyo_path_contains_pattern(name) */ bool is_patterned; /* = tomoyo_path_contains_pattern(name) */
u16 depth; /* = tomoyo_path_depth(name) */
}; };
/* /*
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/mnt_namespace.h> #include <linux/mnt_namespace.h>
#include <linux/fs_struct.h> #include <linux/fs_struct.h>
#include <linux/hash.h>
#include "common.h" #include "common.h"
#include "realpath.h" #include "realpath.h"
...@@ -263,7 +265,8 @@ static unsigned int tomoyo_quota_for_savename; ...@@ -263,7 +265,8 @@ static unsigned int tomoyo_quota_for_savename;
* table. Frequency of appending strings is very low. So we don't need * table. Frequency of appending strings is very low. So we don't need
* large (e.g. 64k) hash size. 256 will be sufficient. * 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 * 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) ...@@ -315,6 +318,7 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name)
struct tomoyo_free_memory_block_list *fmb; struct tomoyo_free_memory_block_list *fmb;
int len; int len;
char *cp; char *cp;
struct list_head *head;
if (!name) if (!name)
return NULL; return NULL;
...@@ -325,9 +329,10 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name) ...@@ -325,9 +329,10 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name)
return NULL; return NULL;
} }
hash = full_name_hash((const unsigned char *) name, len - 1); hash = full_name_hash((const unsigned char *) name, len - 1);
head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)];
mutex_lock(&lock); mutex_lock(&lock);
list_for_each_entry(ptr, &tomoyo_name_list[hash % TOMOYO_MAX_HASH], list_for_each_entry(ptr, head, list) {
list) {
if (hash == ptr->entry.hash && !strcmp(name, ptr->entry.name)) if (hash == ptr->entry.hash && !strcmp(name, ptr->entry.name))
goto out; goto out;
} }
...@@ -365,7 +370,7 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name) ...@@ -365,7 +370,7 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name)
tomoyo_fill_path_info(&ptr->entry); tomoyo_fill_path_info(&ptr->entry);
fmb->ptr += len; fmb->ptr += len;
fmb->len -= 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) { if (fmb->len == 0) {
list_del(&fmb->list); list_del(&fmb->list);
kfree(fmb); 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