Skip to content

Commit 5825a95

Browse files
committed
Merge tag 'selinux-pr-20190917' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux
Pull selinux updates from Paul Moore: - Add LSM hooks, and SELinux access control hooks, for dnotify, fanotify, and inotify watches. This has been discussed with both the LSM and fs/notify folks and everybody is good with these new hooks. - The LSM stacking changes missed a few calls to current_security() in the SELinux code; we fix those and remove current_security() for good. - Improve our network object labeling cache so that we always return the object's label, even when under memory pressure. Previously we would return an error if we couldn't allocate a new cache entry, now we always return the label even if we can't create a new cache entry for it. - Convert the sidtab atomic_t counter to a normal u32 with READ/WRITE_ONCE() and memory barrier protection. - A few patches to policydb.c to clean things up (remove forward declarations, long lines, bad variable names, etc) * tag 'selinux-pr-20190917' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux: lsm: remove current_security() selinux: fix residual uses of current_security() for the SELinux blob selinux: avoid atomic_t usage in sidtab fanotify, inotify, dnotify, security: add security hook for fs notifications selinux: always return a secid from the network caches if we find one selinux: policydb - rename type_val_to_struct_array selinux: policydb - fix some checkpatch.pl warnings selinux: shuffle around policydb.c to get rid of forward declarations
2 parents 3c6a691 + 15322a0 commit 5825a95

File tree

18 files changed

+403
-307
lines changed

18 files changed

+403
-307
lines changed

fs/notify/dnotify/dnotify.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/sched/signal.h>
1414
#include <linux/dnotify.h>
1515
#include <linux/init.h>
16+
#include <linux/security.h>
1617
#include <linux/spinlock.h>
1718
#include <linux/slab.h>
1819
#include <linux/fdtable.h>
@@ -279,6 +280,17 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
279280
goto out_err;
280281
}
281282

283+
/*
284+
* convert the userspace DN_* "arg" to the internal FS_*
285+
* defined in fsnotify
286+
*/
287+
mask = convert_arg(arg);
288+
289+
error = security_path_notify(&filp->f_path, mask,
290+
FSNOTIFY_OBJ_TYPE_INODE);
291+
if (error)
292+
goto out_err;
293+
282294
/* expect most fcntl to add new rather than augment old */
283295
dn = kmem_cache_alloc(dnotify_struct_cache, GFP_KERNEL);
284296
if (!dn) {
@@ -293,9 +305,6 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
293305
goto out_err;
294306
}
295307

296-
/* convert the userspace DN_* "arg" to the internal FS_* defines in fsnotify */
297-
mask = convert_arg(arg);
298-
299308
/* set up the new_fsn_mark and new_dn_mark */
300309
new_fsn_mark = &new_dn_mark->fsn_mark;
301310
fsnotify_init_mark(new_fsn_mark, dnotify_group);

fs/notify/fanotify/fanotify_user.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,8 @@ static const struct file_operations fanotify_fops = {
528528
};
529529

530530
static int fanotify_find_path(int dfd, const char __user *filename,
531-
struct path *path, unsigned int flags)
531+
struct path *path, unsigned int flags, __u64 mask,
532+
unsigned int obj_type)
532533
{
533534
int ret;
534535

@@ -567,8 +568,15 @@ static int fanotify_find_path(int dfd, const char __user *filename,
567568

568569
/* you can only watch an inode if you have read permissions on it */
569570
ret = inode_permission(path->dentry->d_inode, MAY_READ);
571+
if (ret) {
572+
path_put(path);
573+
goto out;
574+
}
575+
576+
ret = security_path_notify(path, mask, obj_type);
570577
if (ret)
571578
path_put(path);
579+
572580
out:
573581
return ret;
574582
}
@@ -947,6 +955,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
947955
__kernel_fsid_t __fsid, *fsid = NULL;
948956
u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS;
949957
unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS;
958+
unsigned int obj_type;
950959
int ret;
951960

952961
pr_debug("%s: fanotify_fd=%d flags=%x dfd=%d pathname=%p mask=%llx\n",
@@ -961,8 +970,13 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
961970

962971
switch (mark_type) {
963972
case FAN_MARK_INODE:
973+
obj_type = FSNOTIFY_OBJ_TYPE_INODE;
974+
break;
964975
case FAN_MARK_MOUNT:
976+
obj_type = FSNOTIFY_OBJ_TYPE_VFSMOUNT;
977+
break;
965978
case FAN_MARK_FILESYSTEM:
979+
obj_type = FSNOTIFY_OBJ_TYPE_SB;
966980
break;
967981
default:
968982
return -EINVAL;
@@ -1030,7 +1044,8 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
10301044
goto fput_and_out;
10311045
}
10321046

1033-
ret = fanotify_find_path(dfd, pathname, &path, flags);
1047+
ret = fanotify_find_path(dfd, pathname, &path, flags,
1048+
(mask & ALL_FSNOTIFY_EVENTS), obj_type);
10341049
if (ret)
10351050
goto fput_and_out;
10361051

fs/notify/inotify/inotify_user.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <linux/poll.h>
3131
#include <linux/wait.h>
3232
#include <linux/memcontrol.h>
33+
#include <linux/security.h>
3334

3435
#include "inotify.h"
3536
#include "../fdinfo.h"
@@ -331,7 +332,8 @@ static const struct file_operations inotify_fops = {
331332
/*
332333
* find_inode - resolve a user-given path to a specific inode
333334
*/
334-
static int inotify_find_inode(const char __user *dirname, struct path *path, unsigned flags)
335+
static int inotify_find_inode(const char __user *dirname, struct path *path,
336+
unsigned int flags, __u64 mask)
335337
{
336338
int error;
337339

@@ -340,8 +342,15 @@ static int inotify_find_inode(const char __user *dirname, struct path *path, uns
340342
return error;
341343
/* you can only watch an inode if you have read permissions on it */
342344
error = inode_permission(path->dentry->d_inode, MAY_READ);
345+
if (error) {
346+
path_put(path);
347+
return error;
348+
}
349+
error = security_path_notify(path, mask,
350+
FSNOTIFY_OBJ_TYPE_INODE);
343351
if (error)
344352
path_put(path);
353+
345354
return error;
346355
}
347356

@@ -733,7 +742,8 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname,
733742
if (mask & IN_ONLYDIR)
734743
flags |= LOOKUP_DIRECTORY;
735744

736-
ret = inotify_find_inode(pathname, &path, flags);
745+
ret = inotify_find_inode(pathname, &path, flags,
746+
(mask & IN_ALL_EVENTS));
737747
if (ret)
738748
goto fput_and_out;
739749

include/linux/cred.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,6 @@ static inline void put_cred(const struct cred *_cred)
386386
#define current_fsgid() (current_cred_xxx(fsgid))
387387
#define current_cap() (current_cred_xxx(cap_effective))
388388
#define current_user() (current_cred_xxx(user))
389-
#define current_security() (current_cred_xxx(security))
390389

391390
extern struct user_namespace init_user_ns;
392391
#ifdef CONFIG_USER_NS

include/linux/lsm_hooks.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,9 @@
339339
* Check for permission to change root directory.
340340
* @path contains the path structure.
341341
* Return 0 if permission is granted.
342+
* @path_notify:
343+
* Check permissions before setting a watch on events as defined by @mask,
344+
* on an object at @path, whose type is defined by @obj_type.
342345
* @inode_readlink:
343346
* Check the permission to read the symbolic link.
344347
* @dentry contains the dentry structure for the file link.
@@ -1535,7 +1538,9 @@ union security_list_options {
15351538
int (*path_chown)(const struct path *path, kuid_t uid, kgid_t gid);
15361539
int (*path_chroot)(const struct path *path);
15371540
#endif
1538-
1541+
/* Needed for inode based security check */
1542+
int (*path_notify)(const struct path *path, u64 mask,
1543+
unsigned int obj_type);
15391544
int (*inode_alloc_security)(struct inode *inode);
15401545
void (*inode_free_security)(struct inode *inode);
15411546
int (*inode_init_security)(struct inode *inode, struct inode *dir,
@@ -1860,6 +1865,8 @@ struct security_hook_heads {
18601865
struct hlist_head path_chown;
18611866
struct hlist_head path_chroot;
18621867
#endif
1868+
/* Needed for inode based modules as well */
1869+
struct hlist_head path_notify;
18631870
struct hlist_head inode_alloc_security;
18641871
struct hlist_head inode_free_security;
18651872
struct hlist_head inode_init_security;

include/linux/security.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,8 @@ int security_dentry_create_files_as(struct dentry *dentry, int mode,
259259
struct qstr *name,
260260
const struct cred *old,
261261
struct cred *new);
262-
262+
int security_path_notify(const struct path *path, u64 mask,
263+
unsigned int obj_type);
263264
int security_inode_alloc(struct inode *inode);
264265
void security_inode_free(struct inode *inode);
265266
int security_inode_init_security(struct inode *inode, struct inode *dir,
@@ -387,7 +388,6 @@ int security_ismaclabel(const char *name);
387388
int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
388389
int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
389390
void security_release_secctx(char *secdata, u32 seclen);
390-
391391
void security_inode_invalidate_secctx(struct inode *inode);
392392
int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
393393
int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
@@ -621,6 +621,12 @@ static inline int security_move_mount(const struct path *from_path,
621621
return 0;
622622
}
623623

624+
static inline int security_path_notify(const struct path *path, u64 mask,
625+
unsigned int obj_type)
626+
{
627+
return 0;
628+
}
629+
624630
static inline int security_inode_alloc(struct inode *inode)
625631
{
626632
return 0;

security/security.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,12 @@ int security_move_mount(const struct path *from_path, const struct path *to_path
870870
return call_int_hook(move_mount, 0, from_path, to_path);
871871
}
872872

873+
int security_path_notify(const struct path *path, u64 mask,
874+
unsigned int obj_type)
875+
{
876+
return call_int_hook(path_notify, 0, path, mask, obj_type);
877+
}
878+
873879
int security_inode_alloc(struct inode *inode)
874880
{
875881
int rc = lsm_inode_alloc(inode);

security/selinux/hooks.c

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@
8989
#include <linux/kernfs.h>
9090
#include <linux/stringhash.h> /* for hashlen_string() */
9191
#include <uapi/linux/mount.h>
92+
#include <linux/fsnotify.h>
93+
#include <linux/fanotify.h>
9294

9395
#include "avc.h"
9496
#include "objsec.h"
@@ -3275,6 +3277,50 @@ static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
32753277
return -EACCES;
32763278
}
32773279

3280+
static int selinux_path_notify(const struct path *path, u64 mask,
3281+
unsigned int obj_type)
3282+
{
3283+
int ret;
3284+
u32 perm;
3285+
3286+
struct common_audit_data ad;
3287+
3288+
ad.type = LSM_AUDIT_DATA_PATH;
3289+
ad.u.path = *path;
3290+
3291+
/*
3292+
* Set permission needed based on the type of mark being set.
3293+
* Performs an additional check for sb watches.
3294+
*/
3295+
switch (obj_type) {
3296+
case FSNOTIFY_OBJ_TYPE_VFSMOUNT:
3297+
perm = FILE__WATCH_MOUNT;
3298+
break;
3299+
case FSNOTIFY_OBJ_TYPE_SB:
3300+
perm = FILE__WATCH_SB;
3301+
ret = superblock_has_perm(current_cred(), path->dentry->d_sb,
3302+
FILESYSTEM__WATCH, &ad);
3303+
if (ret)
3304+
return ret;
3305+
break;
3306+
case FSNOTIFY_OBJ_TYPE_INODE:
3307+
perm = FILE__WATCH;
3308+
break;
3309+
default:
3310+
return -EINVAL;
3311+
}
3312+
3313+
/* blocking watches require the file:watch_with_perm permission */
3314+
if (mask & (ALL_FSNOTIFY_PERM_EVENTS))
3315+
perm |= FILE__WATCH_WITH_PERM;
3316+
3317+
/* watches on read-like events need the file:watch_reads permission */
3318+
if (mask & (FS_ACCESS | FS_ACCESS_PERM | FS_CLOSE_NOWRITE))
3319+
perm |= FILE__WATCH_READS;
3320+
3321+
return path_has_perm(current_cred(), path, perm);
3322+
}
3323+
32783324
/*
32793325
* Copy the inode security context value to the user.
32803326
*
@@ -3403,7 +3449,7 @@ static int selinux_inode_copy_up_xattr(const char *name)
34033449
static int selinux_kernfs_init_security(struct kernfs_node *kn_dir,
34043450
struct kernfs_node *kn)
34053451
{
3406-
const struct task_security_struct *tsec = current_security();
3452+
const struct task_security_struct *tsec = selinux_cred(current_cred());
34073453
u32 parent_sid, newsid, clen;
34083454
int rc;
34093455
char *context;
@@ -6818,6 +6864,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
68186864
LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
68196865
LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up),
68206866
LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr),
6867+
LSM_HOOK_INIT(path_notify, selinux_path_notify),
68216868

68226869
LSM_HOOK_INIT(kernfs_init_security, selinux_kernfs_init_security),
68236870

security/selinux/include/classmap.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88
#define COMMON_FILE_PERMS COMMON_FILE_SOCK_PERMS, "unlink", "link", \
99
"rename", "execute", "quotaon", "mounton", "audit_access", \
10-
"open", "execmod"
10+
"open", "execmod", "watch", "watch_mount", "watch_sb", \
11+
"watch_with_perm", "watch_reads"
1112

1213
#define COMMON_SOCK_PERMS COMMON_FILE_SOCK_PERMS, "bind", "connect", \
1314
"listen", "accept", "getopt", "setopt", "shutdown", "recvfrom", \
@@ -60,7 +61,7 @@ struct security_class_mapping secclass_map[] = {
6061
{ "filesystem",
6162
{ "mount", "remount", "unmount", "getattr",
6263
"relabelfrom", "relabelto", "associate", "quotamod",
63-
"quotaget", NULL } },
64+
"quotaget", "watch", NULL } },
6465
{ "file",
6566
{ COMMON_FILE_PERMS,
6667
"execute_no_trans", "entrypoint", NULL } },

security/selinux/include/objsec.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,6 @@ struct task_security_struct {
3737
u32 sockcreate_sid; /* fscreate SID */
3838
};
3939

40-
/*
41-
* get the subjective security ID of the current task
42-
*/
43-
static inline u32 current_sid(void)
44-
{
45-
const struct task_security_struct *tsec = current_security();
46-
47-
return tsec->sid;
48-
}
49-
5040
enum label_initialized {
5141
LABEL_INVALID, /* invalid or not initialized */
5242
LABEL_INITIALIZED, /* initialized */
@@ -185,4 +175,14 @@ static inline struct ipc_security_struct *selinux_ipc(
185175
return ipc->security + selinux_blob_sizes.lbs_ipc;
186176
}
187177

178+
/*
179+
* get the subjective security ID of the current task
180+
*/
181+
static inline u32 current_sid(void)
182+
{
183+
const struct task_security_struct *tsec = selinux_cred(current_cred());
184+
185+
return tsec->sid;
186+
}
187+
188188
#endif /* _SELINUX_OBJSEC_H_ */

0 commit comments

Comments
 (0)