diff options
-rw-r--r-- | include/linux/security.h | 55 | ||||
-rw-r--r-- | security/capability.c | 17 | ||||
-rw-r--r-- | security/security.c | 18 | ||||
-rw-r--r-- | security/selinux/hooks.c | 29 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 24 |
5 files changed, 143 insertions, 0 deletions
diff --git a/include/linux/security.h b/include/linux/security.h index 10a09257952b..d050b66ab9ef 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -1382,6 +1382,41 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
1382 | * audit_rule_init. | 1382 | * audit_rule_init. |
1383 | * @rule contains the allocated rule | 1383 | * @rule contains the allocated rule |
1384 | * | 1384 | * |
1385 | * @inode_notifysecctx: | ||
1386 | * Notify the security module of what the security context of an inode | ||
1387 | * should be. Initializes the incore security context managed by the | ||
1388 | * security module for this inode. Example usage: NFS client invokes | ||
1389 | * this hook to initialize the security context in its incore inode to the | ||
1390 | * value provided by the server for the file when the server returned the | ||
1391 | * file's attributes to the client. | ||
1392 | * | ||
1393 | * Must be called with inode->i_mutex locked. | ||
1394 | * | ||
1395 | * @inode we wish to set the security context of. | ||
1396 | * @ctx contains the string which we wish to set in the inode. | ||
1397 | * @ctxlen contains the length of @ctx. | ||
1398 | * | ||
1399 | * @inode_setsecctx: | ||
1400 | * Change the security context of an inode. Updates the | ||
1401 | * incore security context managed by the security module and invokes the | ||
1402 | * fs code as needed (via __vfs_setxattr_noperm) to update any backing | ||
1403 | * xattrs that represent the context. Example usage: NFS server invokes | ||
1404 | * this hook to change the security context in its incore inode and on the | ||
1405 | * backing filesystem to a value provided by the client on a SETATTR | ||
1406 | * operation. | ||
1407 | * | ||
1408 | * Must be called with inode->i_mutex locked. | ||
1409 | * | ||
1410 | * @dentry contains the inode we wish to set the security context of. | ||
1411 | * @ctx contains the string which we wish to set in the inode. | ||
1412 | * @ctxlen contains the length of @ctx. | ||
1413 | * | ||
1414 | * @inode_getsecctx: | ||
1415 | * Returns a string containing all relavent security context information | ||
1416 | * | ||
1417 | * @inode we wish to set the security context of. | ||
1418 | * @ctx is a pointer in which to place the allocated security context. | ||
1419 | * @ctxlen points to the place to put the length of @ctx. | ||
1385 | * This is the main security structure. | 1420 | * This is the main security structure. |
1386 | */ | 1421 | */ |
1387 | struct security_operations { | 1422 | struct security_operations { |
@@ -1590,6 +1625,10 @@ struct security_operations { | |||
1590 | int (*secctx_to_secid) (const char *secdata, u32 seclen, u32 *secid); | 1625 | int (*secctx_to_secid) (const char *secdata, u32 seclen, u32 *secid); |
1591 | void (*release_secctx) (char *secdata, u32 seclen); | 1626 | void (*release_secctx) (char *secdata, u32 seclen); |
1592 | 1627 | ||
1628 | int (*inode_notifysecctx)(struct inode *inode, void *ctx, u32 ctxlen); | ||
1629 | int (*inode_setsecctx)(struct dentry *dentry, void *ctx, u32 ctxlen); | ||
1630 | int (*inode_getsecctx)(struct inode *inode, void **ctx, u32 *ctxlen); | ||
1631 | |||
1593 | #ifdef CONFIG_SECURITY_NETWORK | 1632 | #ifdef CONFIG_SECURITY_NETWORK |
1594 | int (*unix_stream_connect) (struct socket *sock, | 1633 | int (*unix_stream_connect) (struct socket *sock, |
1595 | struct socket *other, struct sock *newsk); | 1634 | struct socket *other, struct sock *newsk); |
@@ -1839,6 +1878,9 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); | |||
1839 | int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); | 1878 | int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); |
1840 | void security_release_secctx(char *secdata, u32 seclen); | 1879 | void security_release_secctx(char *secdata, u32 seclen); |
1841 | 1880 | ||
1881 | int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen); | ||
1882 | int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); | ||
1883 | int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen); | ||
1842 | #else /* CONFIG_SECURITY */ | 1884 | #else /* CONFIG_SECURITY */ |
1843 | struct security_mnt_opts { | 1885 | struct security_mnt_opts { |
1844 | }; | 1886 | }; |
@@ -2595,6 +2637,19 @@ static inline int security_secctx_to_secid(const char *secdata, | |||
2595 | static inline void security_release_secctx(char *secdata, u32 seclen) | 2637 | static inline void security_release_secctx(char *secdata, u32 seclen) |
2596 | { | 2638 | { |
2597 | } | 2639 | } |
2640 | |||
2641 | static inline int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) | ||
2642 | { | ||
2643 | return -EOPNOTSUPP; | ||
2644 | } | ||
2645 | static inline int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) | ||
2646 | { | ||
2647 | return -EOPNOTSUPP; | ||
2648 | } | ||
2649 | static inline int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) | ||
2650 | { | ||
2651 | return -EOPNOTSUPP; | ||
2652 | } | ||
2598 | #endif /* CONFIG_SECURITY */ | 2653 | #endif /* CONFIG_SECURITY */ |
2599 | 2654 | ||
2600 | #ifdef CONFIG_SECURITY_NETWORK | 2655 | #ifdef CONFIG_SECURITY_NETWORK |
diff --git a/security/capability.c b/security/capability.c index 93a2ffe65905..fce07a7bc825 100644 --- a/security/capability.c +++ b/security/capability.c | |||
@@ -822,6 +822,20 @@ static void cap_release_secctx(char *secdata, u32 seclen) | |||
822 | { | 822 | { |
823 | } | 823 | } |
824 | 824 | ||
825 | static int cap_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) | ||
826 | { | ||
827 | return 0; | ||
828 | } | ||
829 | |||
830 | static int cap_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) | ||
831 | { | ||
832 | return 0; | ||
833 | } | ||
834 | |||
835 | static int cap_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) | ||
836 | { | ||
837 | return 0; | ||
838 | } | ||
825 | #ifdef CONFIG_KEYS | 839 | #ifdef CONFIG_KEYS |
826 | static int cap_key_alloc(struct key *key, const struct cred *cred, | 840 | static int cap_key_alloc(struct key *key, const struct cred *cred, |
827 | unsigned long flags) | 841 | unsigned long flags) |
@@ -1032,6 +1046,9 @@ void security_fixup_ops(struct security_operations *ops) | |||
1032 | set_to_cap_if_null(ops, secid_to_secctx); | 1046 | set_to_cap_if_null(ops, secid_to_secctx); |
1033 | set_to_cap_if_null(ops, secctx_to_secid); | 1047 | set_to_cap_if_null(ops, secctx_to_secid); |
1034 | set_to_cap_if_null(ops, release_secctx); | 1048 | set_to_cap_if_null(ops, release_secctx); |
1049 | set_to_cap_if_null(ops, inode_notifysecctx); | ||
1050 | set_to_cap_if_null(ops, inode_setsecctx); | ||
1051 | set_to_cap_if_null(ops, inode_getsecctx); | ||
1035 | #ifdef CONFIG_SECURITY_NETWORK | 1052 | #ifdef CONFIG_SECURITY_NETWORK |
1036 | set_to_cap_if_null(ops, unix_stream_connect); | 1053 | set_to_cap_if_null(ops, unix_stream_connect); |
1037 | set_to_cap_if_null(ops, unix_may_send); | 1054 | set_to_cap_if_null(ops, unix_may_send); |
diff --git a/security/security.c b/security/security.c index d8b727637f02..c4c673240c1c 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -974,6 +974,24 @@ void security_release_secctx(char *secdata, u32 seclen) | |||
974 | } | 974 | } |
975 | EXPORT_SYMBOL(security_release_secctx); | 975 | EXPORT_SYMBOL(security_release_secctx); |
976 | 976 | ||
977 | int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) | ||
978 | { | ||
979 | return security_ops->inode_notifysecctx(inode, ctx, ctxlen); | ||
980 | } | ||
981 | EXPORT_SYMBOL(security_inode_notifysecctx); | ||
982 | |||
983 | int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) | ||
984 | { | ||
985 | return security_ops->inode_setsecctx(dentry, ctx, ctxlen); | ||
986 | } | ||
987 | EXPORT_SYMBOL(security_inode_setsecctx); | ||
988 | |||
989 | int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) | ||
990 | { | ||
991 | return security_ops->inode_getsecctx(inode, ctx, ctxlen); | ||
992 | } | ||
993 | EXPORT_SYMBOL(security_inode_getsecctx); | ||
994 | |||
977 | #ifdef CONFIG_SECURITY_NETWORK | 995 | #ifdef CONFIG_SECURITY_NETWORK |
978 | 996 | ||
979 | int security_unix_stream_connect(struct socket *sock, struct socket *other, | 997 | int security_unix_stream_connect(struct socket *sock, struct socket *other, |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 134a9c0d2004..7118be2a74a5 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -5351,6 +5351,32 @@ static void selinux_release_secctx(char *secdata, u32 seclen) | |||
5351 | kfree(secdata); | 5351 | kfree(secdata); |
5352 | } | 5352 | } |
5353 | 5353 | ||
5354 | /* | ||
5355 | * called with inode->i_mutex locked | ||
5356 | */ | ||
5357 | static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) | ||
5358 | { | ||
5359 | return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0); | ||
5360 | } | ||
5361 | |||
5362 | /* | ||
5363 | * called with inode->i_mutex locked | ||
5364 | */ | ||
5365 | static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) | ||
5366 | { | ||
5367 | return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0); | ||
5368 | } | ||
5369 | |||
5370 | static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) | ||
5371 | { | ||
5372 | int len = 0; | ||
5373 | len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX, | ||
5374 | ctx, true); | ||
5375 | if (len < 0) | ||
5376 | return len; | ||
5377 | *ctxlen = len; | ||
5378 | return 0; | ||
5379 | } | ||
5354 | #ifdef CONFIG_KEYS | 5380 | #ifdef CONFIG_KEYS |
5355 | 5381 | ||
5356 | static int selinux_key_alloc(struct key *k, const struct cred *cred, | 5382 | static int selinux_key_alloc(struct key *k, const struct cred *cred, |
@@ -5550,6 +5576,9 @@ static struct security_operations selinux_ops = { | |||
5550 | .secid_to_secctx = selinux_secid_to_secctx, | 5576 | .secid_to_secctx = selinux_secid_to_secctx, |
5551 | .secctx_to_secid = selinux_secctx_to_secid, | 5577 | .secctx_to_secid = selinux_secctx_to_secid, |
5552 | .release_secctx = selinux_release_secctx, | 5578 | .release_secctx = selinux_release_secctx, |
5579 | .inode_notifysecctx = selinux_inode_notifysecctx, | ||
5580 | .inode_setsecctx = selinux_inode_setsecctx, | ||
5581 | .inode_getsecctx = selinux_inode_getsecctx, | ||
5553 | 5582 | ||
5554 | .unix_stream_connect = selinux_socket_unix_stream_connect, | 5583 | .unix_stream_connect = selinux_socket_unix_stream_connect, |
5555 | .unix_may_send = selinux_socket_unix_may_send, | 5584 | .unix_may_send = selinux_socket_unix_may_send, |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 969f5fee1906..0b3bb646f90e 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -3057,6 +3057,27 @@ static void smack_release_secctx(char *secdata, u32 seclen) | |||
3057 | { | 3057 | { |
3058 | } | 3058 | } |
3059 | 3059 | ||
3060 | static int smack_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) | ||
3061 | { | ||
3062 | return smack_inode_setsecurity(inode, XATTR_SMACK_SUFFIX, ctx, ctxlen, 0); | ||
3063 | } | ||
3064 | |||
3065 | static int smack_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) | ||
3066 | { | ||
3067 | return __vfs_setxattr_noperm(dentry, XATTR_NAME_SMACK, ctx, ctxlen, 0); | ||
3068 | } | ||
3069 | |||
3070 | static int smack_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) | ||
3071 | { | ||
3072 | int len = 0; | ||
3073 | len = smack_inode_getsecurity(inode, XATTR_SMACK_SUFFIX, ctx, true); | ||
3074 | |||
3075 | if (len < 0) | ||
3076 | return len; | ||
3077 | *ctxlen = len; | ||
3078 | return 0; | ||
3079 | } | ||
3080 | |||
3060 | struct security_operations smack_ops = { | 3081 | struct security_operations smack_ops = { |
3061 | .name = "smack", | 3082 | .name = "smack", |
3062 | 3083 | ||
@@ -3185,6 +3206,9 @@ struct security_operations smack_ops = { | |||
3185 | .secid_to_secctx = smack_secid_to_secctx, | 3206 | .secid_to_secctx = smack_secid_to_secctx, |
3186 | .secctx_to_secid = smack_secctx_to_secid, | 3207 | .secctx_to_secid = smack_secctx_to_secid, |
3187 | .release_secctx = smack_release_secctx, | 3208 | .release_secctx = smack_release_secctx, |
3209 | .inode_notifysecctx = smack_inode_notifysecctx, | ||
3210 | .inode_setsecctx = smack_inode_setsecctx, | ||
3211 | .inode_getsecctx = smack_inode_getsecctx, | ||
3188 | }; | 3212 | }; |
3189 | 3213 | ||
3190 | 3214 | ||