diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-23 23:44:19 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-23 23:44:19 -0500 |
commit | 1ebbe2b20091d306453a5cf480a87e6cd28ae76f (patch) | |
tree | f5cd7a0fa69b8b1938cb5a0faed2e7b0628072a5 /security/selinux/hooks.c | |
parent | ac58c9059da8886b5e8cde012a80266b18ca146e (diff) | |
parent | 674a396c6d2ba0341ebdd7c1c9950f32f018e2dd (diff) |
Merge branch 'linus'
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 60 |
1 files changed, 48 insertions, 12 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index b65c201e9ff5..ccaf988f3729 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -117,6 +117,8 @@ static struct security_operations *secondary_ops = NULL; | |||
117 | static LIST_HEAD(superblock_security_head); | 117 | static LIST_HEAD(superblock_security_head); |
118 | static DEFINE_SPINLOCK(sb_security_lock); | 118 | static DEFINE_SPINLOCK(sb_security_lock); |
119 | 119 | ||
120 | static kmem_cache_t *sel_inode_cache; | ||
121 | |||
120 | /* Allocate and free functions for each kind of security blob. */ | 122 | /* Allocate and free functions for each kind of security blob. */ |
121 | 123 | ||
122 | static int task_alloc_security(struct task_struct *task) | 124 | static int task_alloc_security(struct task_struct *task) |
@@ -146,10 +148,11 @@ static int inode_alloc_security(struct inode *inode) | |||
146 | struct task_security_struct *tsec = current->security; | 148 | struct task_security_struct *tsec = current->security; |
147 | struct inode_security_struct *isec; | 149 | struct inode_security_struct *isec; |
148 | 150 | ||
149 | isec = kzalloc(sizeof(struct inode_security_struct), GFP_KERNEL); | 151 | isec = kmem_cache_alloc(sel_inode_cache, SLAB_KERNEL); |
150 | if (!isec) | 152 | if (!isec) |
151 | return -ENOMEM; | 153 | return -ENOMEM; |
152 | 154 | ||
155 | memset(isec, 0, sizeof(*isec)); | ||
153 | init_MUTEX(&isec->sem); | 156 | init_MUTEX(&isec->sem); |
154 | INIT_LIST_HEAD(&isec->list); | 157 | INIT_LIST_HEAD(&isec->list); |
155 | isec->inode = inode; | 158 | isec->inode = inode; |
@@ -172,7 +175,7 @@ static void inode_free_security(struct inode *inode) | |||
172 | spin_unlock(&sbsec->isec_lock); | 175 | spin_unlock(&sbsec->isec_lock); |
173 | 176 | ||
174 | inode->i_security = NULL; | 177 | inode->i_security = NULL; |
175 | kfree(isec); | 178 | kmem_cache_free(sel_inode_cache, isec); |
176 | } | 179 | } |
177 | 180 | ||
178 | static int file_alloc_security(struct file *file) | 181 | static int file_alloc_security(struct file *file) |
@@ -1929,7 +1932,6 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
1929 | struct task_security_struct *tsec; | 1932 | struct task_security_struct *tsec; |
1930 | struct inode_security_struct *dsec; | 1933 | struct inode_security_struct *dsec; |
1931 | struct superblock_security_struct *sbsec; | 1934 | struct superblock_security_struct *sbsec; |
1932 | struct inode_security_struct *isec; | ||
1933 | u32 newsid, clen; | 1935 | u32 newsid, clen; |
1934 | int rc; | 1936 | int rc; |
1935 | char *namep = NULL, *context; | 1937 | char *namep = NULL, *context; |
@@ -1937,7 +1939,6 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
1937 | tsec = current->security; | 1939 | tsec = current->security; |
1938 | dsec = dir->i_security; | 1940 | dsec = dir->i_security; |
1939 | sbsec = dir->i_sb->s_security; | 1941 | sbsec = dir->i_sb->s_security; |
1940 | isec = inode->i_security; | ||
1941 | 1942 | ||
1942 | if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { | 1943 | if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { |
1943 | newsid = tsec->create_sid; | 1944 | newsid = tsec->create_sid; |
@@ -1957,7 +1958,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
1957 | 1958 | ||
1958 | inode_security_set_sid(inode, newsid); | 1959 | inode_security_set_sid(inode, newsid); |
1959 | 1960 | ||
1960 | if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT) | 1961 | if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT) |
1961 | return -EOPNOTSUPP; | 1962 | return -EOPNOTSUPP; |
1962 | 1963 | ||
1963 | if (name) { | 1964 | if (name) { |
@@ -3318,24 +3319,38 @@ out: | |||
3318 | return err; | 3319 | return err; |
3319 | } | 3320 | } |
3320 | 3321 | ||
3321 | static int selinux_socket_getpeersec(struct socket *sock, char __user *optval, | 3322 | static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval, |
3322 | int __user *optlen, unsigned len) | 3323 | int __user *optlen, unsigned len) |
3323 | { | 3324 | { |
3324 | int err = 0; | 3325 | int err = 0; |
3325 | char *scontext; | 3326 | char *scontext; |
3326 | u32 scontext_len; | 3327 | u32 scontext_len; |
3327 | struct sk_security_struct *ssec; | 3328 | struct sk_security_struct *ssec; |
3328 | struct inode_security_struct *isec; | 3329 | struct inode_security_struct *isec; |
3330 | u32 peer_sid = 0; | ||
3329 | 3331 | ||
3330 | isec = SOCK_INODE(sock)->i_security; | 3332 | isec = SOCK_INODE(sock)->i_security; |
3331 | if (isec->sclass != SECCLASS_UNIX_STREAM_SOCKET) { | 3333 | |
3334 | /* if UNIX_STREAM check peer_sid, if TCP check dst for labelled sa */ | ||
3335 | if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET) { | ||
3336 | ssec = sock->sk->sk_security; | ||
3337 | peer_sid = ssec->peer_sid; | ||
3338 | } | ||
3339 | else if (isec->sclass == SECCLASS_TCP_SOCKET) { | ||
3340 | peer_sid = selinux_socket_getpeer_stream(sock->sk); | ||
3341 | |||
3342 | if (peer_sid == SECSID_NULL) { | ||
3343 | err = -ENOPROTOOPT; | ||
3344 | goto out; | ||
3345 | } | ||
3346 | } | ||
3347 | else { | ||
3332 | err = -ENOPROTOOPT; | 3348 | err = -ENOPROTOOPT; |
3333 | goto out; | 3349 | goto out; |
3334 | } | 3350 | } |
3335 | 3351 | ||
3336 | ssec = sock->sk->sk_security; | 3352 | err = security_sid_to_context(peer_sid, &scontext, &scontext_len); |
3337 | 3353 | ||
3338 | err = security_sid_to_context(ssec->peer_sid, &scontext, &scontext_len); | ||
3339 | if (err) | 3354 | if (err) |
3340 | goto out; | 3355 | goto out; |
3341 | 3356 | ||
@@ -3356,6 +3371,23 @@ out: | |||
3356 | return err; | 3371 | return err; |
3357 | } | 3372 | } |
3358 | 3373 | ||
3374 | static int selinux_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, u32 *seclen) | ||
3375 | { | ||
3376 | int err = 0; | ||
3377 | u32 peer_sid = selinux_socket_getpeer_dgram(skb); | ||
3378 | |||
3379 | if (peer_sid == SECSID_NULL) | ||
3380 | return -EINVAL; | ||
3381 | |||
3382 | err = security_sid_to_context(peer_sid, secdata, seclen); | ||
3383 | if (err) | ||
3384 | return err; | ||
3385 | |||
3386 | return 0; | ||
3387 | } | ||
3388 | |||
3389 | |||
3390 | |||
3359 | static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) | 3391 | static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) |
3360 | { | 3392 | { |
3361 | return sk_alloc_security(sk, family, priority); | 3393 | return sk_alloc_security(sk, family, priority); |
@@ -4344,7 +4376,8 @@ static struct security_operations selinux_ops = { | |||
4344 | .socket_setsockopt = selinux_socket_setsockopt, | 4376 | .socket_setsockopt = selinux_socket_setsockopt, |
4345 | .socket_shutdown = selinux_socket_shutdown, | 4377 | .socket_shutdown = selinux_socket_shutdown, |
4346 | .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb, | 4378 | .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb, |
4347 | .socket_getpeersec = selinux_socket_getpeersec, | 4379 | .socket_getpeersec_stream = selinux_socket_getpeersec_stream, |
4380 | .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram, | ||
4348 | .sk_alloc_security = selinux_sk_alloc_security, | 4381 | .sk_alloc_security = selinux_sk_alloc_security, |
4349 | .sk_free_security = selinux_sk_free_security, | 4382 | .sk_free_security = selinux_sk_free_security, |
4350 | .sk_getsid = selinux_sk_getsid_security, | 4383 | .sk_getsid = selinux_sk_getsid_security, |
@@ -4376,6 +4409,9 @@ static __init int selinux_init(void) | |||
4376 | tsec = current->security; | 4409 | tsec = current->security; |
4377 | tsec->osid = tsec->sid = SECINITSID_KERNEL; | 4410 | tsec->osid = tsec->sid = SECINITSID_KERNEL; |
4378 | 4411 | ||
4412 | sel_inode_cache = kmem_cache_create("selinux_inode_security", | ||
4413 | sizeof(struct inode_security_struct), | ||
4414 | 0, SLAB_PANIC, NULL, NULL); | ||
4379 | avc_init(); | 4415 | avc_init(); |
4380 | 4416 | ||
4381 | original_ops = secondary_ops = security_ops; | 4417 | original_ops = secondary_ops = security_ops; |