Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

initial commit of extracted grsecurity chroot hardening #1

Closed
wants to merge 34 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
c607904
enable CONFIG_PANIC_ON_OOPS by default
thestinger May 3, 2017
313bc9a
enable CONFIG_DEBUG_LIST by default
thestinger May 3, 2017
ae12fbf
enable SLAB_FREELIST_RANDOM by default
thestinger May 3, 2017
cdb398d
set kptr_restrict=2 by default
thestinger May 3, 2017
e32ea1a
add __ro_after_init to slab_nomerge
thestinger May 3, 2017
b835fbc
add a SLAB_HARDENED configuration option
thestinger May 3, 2017
8f36fe9
disable slab merging
thestinger May 3, 2017
b238307
add missing cache_from_obj !PageSlab check
thestinger May 3, 2017
133cc26
real slab_equal_or_root check for !MEMCG_KMEM
thestinger Mar 31, 2017
e45250a
bug on kmem_cache_free with the wrong cache
thestinger May 3, 2017
6e098ef
always perform cache_from_obj consistency checks
thestinger May 3, 2017
eb54ce7
bug on !PageSlab && !PageCompound in ksize
thestinger May 3, 2017
6efe84c
add kmalloc alloc_size attributes
thestinger May 3, 2017
d342da3
add vmalloc alloc_size attributes
thestinger May 3, 2017
e1f59d4
arm64: zero the leading stack canary byte
thestinger May 3, 2017
624349a
x86_64: zero the leading stack canary byte
thestinger May 3, 2017
0926d3f
use get_random_long for the per-task stack canary
thestinger May 3, 2017
daaf36f
zero leading per-task stack canary byte on 64-bit
thestinger May 3, 2017
e1d4586
add slub free list XOR encryption
thestinger May 3, 2017
7048d1b
add fortified string.h functions
thestinger Apr 9, 2017
4764563
work around undefined memcmp in arch/arm64/kernel/vdso.c
thestinger Apr 9, 2017
7a841c1
work around undefined memcmp in kernel/kexec_file.c
thestinger May 3, 2017
46e3c06
work around undefined memcpy in drivers/net/ethernet/brocade/bna/bnad…
thestinger May 3, 2017
9e2e0bd
work around undefined memcpy in drivers/net/ethernet/brocade/bna/bfa_…
thestinger May 3, 2017
3222859
work around undefined memcpy calls in drivers/net/ethernet/qlogic/qlg…
thestinger May 3, 2017
0638b18
work around undefined memcpy in drivers/net/wireless/marvell/libertas…
thestinger May 3, 2017
81f5f22
work around undefined memcpy in drivers/net/wireless/ray_cs.c
thestinger May 3, 2017
bfe45e0
work around undefined memcpy in drivers/scsi/csiostor/csio_lnode.c
thestinger May 3, 2017
e20aada
add basic full slab sanitization
thestinger May 3, 2017
c8e0e67
slub: add multi-purpose random canaries
thestinger May 3, 2017
7538062
initial commit of extracted grsecurity chroot hardening
andyrj May 4, 2017
b5d9315
corrected error from a squash merge, left GRKERNSEC and grsec_, inste…
andyrj May 4, 2017
5e51c71
missed another rename in squash merge for handle_chroot_sysctl
andyrj May 4, 2017
8e43a35
another rename correction missed in initial merge
andyrj May 4, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions arch/arm64/include/asm/stackprotector.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ static __always_inline void boot_init_stack_canary(void)
get_random_bytes(&canary, sizeof(canary));
canary ^= LINUX_VERSION_CODE;

/* Sacrifice 8 bits of entropy to mitigate non-terminated C string overflows */
canary &= ~(unsigned long)0xff;

current->stack_canary = canary;
__stack_chk_guard = current->stack_canary;
}
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/kernel/vdso.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ static int __init vdso_init(void)
struct page **vdso_pagelist;
unsigned long pfn;

if (memcmp(&vdso_start, "\177ELF", 4)) {
if (__builtin_memcmp(&vdso_start, "\177ELF", 4)) {
pr_err("vDSO is not a valid ELF object!\n");
return -EINVAL;
}
Expand Down
5 changes: 5 additions & 0 deletions arch/x86/boot/compressed/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -409,3 +409,8 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
debug_putstr("done.\nBooting the kernel.\n");
return output;
}

void fortify_panic(const char *name)
{
error("detected buffer overflow");
}
5 changes: 5 additions & 0 deletions arch/x86/include/asm/stackprotector.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ static __always_inline void boot_init_stack_canary(void)
tsc = rdtsc();
canary += tsc + (tsc << 32UL);

#ifdef CONFIG_X86_64
/* Sacrifice 8 bits of entropy to mitigate non-terminated C string overflows */
canary &= ~(unsigned long)0xff;
#endif

current->stack_canary = canary;
#ifdef CONFIG_X86_64
this_cpu_write(irq_stack_union.stack_canary, canary);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/brocade/bna/bfa_ioc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2845,7 +2845,7 @@ bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc, char *optrom_ver)
static void
bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc, char *manufacturer)
{
memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);
__builtin_memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);
}

static void
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/brocade/bna/bnad_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ bnad_get_strings(struct net_device *netdev, u32 stringset, u8 *string)
for (i = 0; i < BNAD_ETHTOOL_STATS_NUM; i++) {
BUG_ON(!(strlen(bnad_net_stats_strings[i]) <
ETH_GSTRING_LEN));
memcpy(string, bnad_net_stats_strings[i],
__builtin_memcpy(string, bnad_net_stats_strings[i],
ETH_GSTRING_LEN);
string += ETH_GSTRING_LEN;
}
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/qlogic/qlge/qlge_dbg.c
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
sizeof(struct mpi_coredump_global_header);
mpi_coredump->mpi_global_header.imageSize =
sizeof(struct ql_mpi_coredump);
memcpy(mpi_coredump->mpi_global_header.idString, "MPI Coredump",
__builtin_memcpy(mpi_coredump->mpi_global_header.idString, "MPI Coredump",
sizeof(mpi_coredump->mpi_global_header.idString));

/* Get generic NIC reg dump */
Expand Down Expand Up @@ -1255,7 +1255,7 @@ static void ql_gen_reg_dump(struct ql_adapter *qdev,
sizeof(struct mpi_coredump_global_header);
mpi_coredump->mpi_global_header.imageSize =
sizeof(struct ql_reg_dump);
memcpy(mpi_coredump->mpi_global_header.idString, "MPI Coredump",
__builtin_memcpy(mpi_coredump->mpi_global_header.idString, "MPI Coredump",
sizeof(mpi_coredump->mpi_global_header.idString));


Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/marvell/libertas/mesh.c
Original file line number Diff line number Diff line change
Expand Up @@ -1177,7 +1177,7 @@ void lbs_mesh_ethtool_get_strings(struct net_device *dev,
switch (stringset) {
case ETH_SS_STATS:
for (i = 0; i < MESH_STATS_NUM; i++) {
memcpy(s + i * ETH_GSTRING_LEN,
__builtin_memcpy(s + i * ETH_GSTRING_LEN,
mesh_stat_strings[i],
ETH_GSTRING_LEN);
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/ray_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ static void init_startup_params(ray_dev_t *local)
* a_beacon_period = hops a_beacon_period = KuS
*//* 64ms = 010000 */
if (local->fw_ver == 0x55) {
memcpy((UCHAR *) &local->sparm.b4, b4_default_startup_parms,
__builtin_memcpy((UCHAR *) &local->sparm.b4, b4_default_startup_parms,
sizeof(struct b4_startup_params));
/* Translate sane kus input values to old build 4/5 format */
/* i = hop time in uS truncated to 3 bytes */
Expand Down
2 changes: 1 addition & 1 deletion drivers/scsi/csiostor/csio_lnode.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ csio_append_attrib(uint8_t **ptr, uint16_t type, uint8_t *val, uint16_t len)
len += 4; /* includes attribute type and length */
len = (len + 3) & ~3; /* should be multiple of 4 bytes */
ae->len = htons(len);
memcpy(ae->value, val, len);
__builtin_memcpy(ae->value, val, len);
*ptr += len;
}

Expand Down
4 changes: 3 additions & 1 deletion fs/fcntl.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#include <linux/pid_namespace.h>
#include <linux/user_namespace.h>
#include <linux/shmem_fs.h>

#include <linux/hardened.h>
#include <asm/poll.h>
#include <asm/siginfo.h>
#include <linux/uaccess.h>
Expand Down Expand Up @@ -104,6 +104,8 @@ void __f_setown(struct file *filp, struct pid *pid, enum pid_type type,
int force)
{
security_file_set_fowner(filp);
if (handle_chroot_fowner(pid, type))
return;
f_modown(filp, pid, type, force);
}
EXPORT_SYMBOL(__f_setown);
Expand Down
3 changes: 2 additions & 1 deletion fs/fhandle.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <linux/fsnotify.h>
#include <linux/personality.h>
#include <linux/uaccess.h>
#include <linux/hardened.h>
#include "internal.h"
#include "mount.h"

Expand Down Expand Up @@ -175,7 +176,7 @@ static int handle_to_path(int mountdirfd, struct file_handle __user *ufh,
* the directory. Ideally we would like CAP_DAC_SEARCH.
* But we don't have that
*/
if (!capable(CAP_DAC_READ_SEARCH)) {
if (!capable(CAP_DAC_READ_SEARCH) || !chroot_fhandle()) {
retval = -EPERM;
goto out_err;
}
Expand Down
11 changes: 10 additions & 1 deletion fs/fs_struct.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <linux/path.h>
#include <linux/slab.h>
#include <linux/fs_struct.h>
#include <linux/hardened.h>
#include "internal.h"

/*
Expand All @@ -16,14 +17,18 @@ void set_fs_root(struct fs_struct *fs, const struct path *path)
struct path old_root;

path_get(path);
inc_chroot_refcnts(path->dentry, path->mnt);
spin_lock(&fs->lock);
write_seqcount_begin(&fs->seq);
old_root = fs->root;
fs->root = *path;
set_chroot_entries(current, path);
write_seqcount_end(&fs->seq);
spin_unlock(&fs->lock);
if (old_root.dentry)
if (old_root.dentry) {
dec_chroot_refcnts(old_root.dentry, old_root.mnt);
path_put(&old_root);
}
}

/*
Expand Down Expand Up @@ -86,6 +91,7 @@ void chroot_fs_refs(const struct path *old_root, const struct path *new_root)

void free_fs_struct(struct fs_struct *fs)
{
dec_chroot_refcnts(fs->root.dentry, fs->root.mnt);
path_put(&fs->root);
path_put(&fs->pwd);
kmem_cache_free(fs_cachep, fs);
Expand All @@ -100,6 +106,7 @@ void exit_fs(struct task_struct *tsk)
task_lock(tsk);
spin_lock(&fs->lock);
tsk->fs = NULL;
clear_chroot_entries(tsk);
kill = !--fs->users;
spin_unlock(&fs->lock);
task_unlock(tsk);
Expand All @@ -125,6 +132,7 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old)
fs->pwd = old->pwd;
path_get(&fs->pwd);
spin_unlock(&old->lock);
inc_chroot_refcnts(fs->root.dentry, fs->root.mnt);
}
return fs;
}
Expand All @@ -142,6 +150,7 @@ int unshare_fs_struct(void)
spin_lock(&fs->lock);
kill = !--fs->users;
current->fs = new_fs;
set_chroot_entries(current, &new_fs->root);
spin_unlock(&fs->lock);
task_unlock(current);

Expand Down
29 changes: 27 additions & 2 deletions fs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
#include <linux/bitops.h>
#include <linux/init_task.h>
#include <linux/uaccess.h>

#include <linux/hardened.h>
#include "internal.h"
#include "mount.h"

Expand Down Expand Up @@ -2277,6 +2277,10 @@ static int path_lookupat(struct nameidata *nd, unsigned flags, struct path *path
if (!err)
err = complete_walk(nd);

if (!err && !(nd->flags & LOOKUP_PARENT)) {
err = chroot_pathat(nd->dfd, nd->path.dentry, nd->path.mnt, nd->flags);
}

if (!err && nd->flags & LOOKUP_DIRECTORY)
if (!d_can_lookup(nd->path.dentry))
err = -ENOTDIR;
Expand Down Expand Up @@ -2324,7 +2328,9 @@ static int path_parentat(struct nameidata *nd, unsigned flags,
return PTR_ERR(s);
err = link_path_walk(s, nd);
if (!err)
err = complete_walk(nd);
err = complete_walk(nd);
if (!err)
err = chroot_pathat(nd->dfd, nd->path.dentry, nd->path.mnt, nd->flags);
if (!err) {
*parent = nd->path;
nd->path.mnt = NULL;
Expand Down Expand Up @@ -3159,6 +3165,10 @@ static int lookup_open(struct nameidata *nd, struct path *path,

/* Negative dentry, just create the file */
if (!dentry->d_inode && (open_flag & O_CREAT)) {
error = chroot_pathat(nd->dfd, dentry, nd->path.mnt, nd->flags);
if (error)
goto out_dput;

*opened |= FILE_CREATED;
audit_inode_child(dir_inode, dentry, AUDIT_TYPE_CHILD_CREATE);
if (!dir_inode->i_op->create) {
Expand Down Expand Up @@ -3323,6 +3333,10 @@ static int do_last(struct nameidata *nd,
error = complete_walk(nd);
if (error)
return error;
error = chroot_pathat(nd->dfd, nd->path.dentry, nd->path.mnt, nd->flags);
if (error)
goto out;

audit_inode(nd->name, nd->path.dentry, 0);
error = -EISDIR;
if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry))
Expand Down Expand Up @@ -3716,6 +3730,10 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode,

if (!IS_POSIXACL(path.dentry->d_inode))
mode &= ~current_umask();
if (handle_chroot_mknod(dentry, path.mnt, mode)) {
error = -EPERM;
goto out;
}
error = security_path_mknod(&path, dentry, mode, dev);
if (error)
goto out;
Expand Down Expand Up @@ -4555,6 +4573,13 @@ SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname,
error = -ENOTEMPTY;
if (new_dentry == trap)
goto exit5;
if (bad_chroot_rename(old_dentry, old_path.mnt, new_dentry, new_path.mnt)) {
/* use EXDEV error to cause 'mv' to switch to an alternative
* method for usability
*/
error = -EXDEV;
goto exit5;
}

error = security_path_rename(&old_path, old_dentry,
&new_path, new_dentry, flags);
Expand Down
11 changes: 10 additions & 1 deletion fs/namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#include <linux/bootmem.h>
#include <linux/task_work.h>
#include <linux/sched/task.h>

#include <linux/hardened.h>
#include "pnode.h"
#include "internal.h"

Expand Down Expand Up @@ -2812,6 +2812,11 @@ long do_mount(const char *dev_name, const char __user *dir_name,
if (flags & MS_RDONLY)
mnt_flags |= MNT_READONLY;

if (handle_chroot_mount(path.dentry, path.mnt, dev_name)) {
retval = -EPERM;
goto dput_out;
}

/* The default atime for remount is preservation */
if ((flags & MS_REMOUNT) &&
((flags & (MS_NOATIME | MS_NODIRATIME | MS_RELATIME |
Expand Down Expand Up @@ -3133,6 +3138,10 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
error = security_sb_pivotroot(&old, &new);
if (error)
goto out2;
if (handle_chroot_pivot()) {
error = -EPERM;
goto out2;
}

get_fs_root(current->fs, &root);
old_mp = lock_mount(&old);
Expand Down
13 changes: 12 additions & 1 deletion fs/open.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
#include <linux/ima.h>
#include <linux/dnotify.h>
#include <linux/compat.h>

#include <linux/hardened.h>
#include "internal.h"

int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
Expand Down Expand Up @@ -473,6 +473,8 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd)
goto out_putf;

error = inode_permission(inode, MAY_EXEC | MAY_CHDIR);
if (!error && !chroot_fchdir(f.file->f_path.dentry, f.file->f_path.mnt))
error = -EPERM;
if (!error)
set_fs_pwd(current->fs, &f.file->f_path);
out_putf:
Expand Down Expand Up @@ -501,8 +503,11 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename)
error = security_path_chroot(&path);
if (error)
goto dput_and_out;
if (handle_chroot_chroot(path.dentry, path.mnt))
goto dput_and_out;

set_fs_root(current->fs, &path);
handle_chroot_chdir(&path);
error = 0;
dput_and_out:
path_put(&path);
Expand All @@ -526,6 +531,12 @@ static int chmod_common(const struct path *path, umode_t mode)
return error;
retry_deleg:
inode_lock(inode);

if (handle_chroot_chmod(path->dentry, path->mnt, mode)) {
error = -EACCES;
goto out_unlock;
}

error = security_path_chmod(path, mode);
if (error)
goto out_unlock;
Expand Down
Loading