Hi, James, Stephen, Dave and Chris,

Enclosed please find the updated AF_UNIX patch.  It addressed three major
issues in the previous patch.

1. No directly calling of the SELINUX function security_sid_to_context().
   The fix is to export this and other similar functions through
   wrapper functions in selinux/exports.c.  Most of this code is copied
   from James' outstanding patch:
   
http://people.redhat.com/jmorris/selinux/skfilter/kernel/12-skfilter-selinux-exports.patch

2. Potential performance problem due to the call to sk_callback_lock() in
   security_sk_sid().
   The fix is to introduce a new function selinux_sock_ctxid() that 
   retrieves the sid of a socket w/o locking.

3. scm_send() might generate garbage sid, if SELINUX is not enabled.
   The fix is to have selinux_id_to_ctx() return ENOTSUPP when SELINUX
   is not enabled, so that no control message will be generated.

Again, my sincere apologies for the delayed response.  As always, comments 
are appreciated!

thanks,
Catherine

----

From: [EMAIL PROTECTED]

This patch implements an API whereby an application can determine the 
label of its peer's Unix datagram sockets via the auxiliary data mechanism of 
recvmsg.

Patch purpose:

This patch enables a security-aware application to retrieve the
security context of the peer of a Unix datagram socket.  The application 
can then use this security context to determine the security context for 
processing on behalf of the peer who sent the packet. 

Patch design and implementation:

The design and implementation is very similar to the UDP case for INET 
sockets.  Basically we build upon the existing Unix domain socket API for
retrieving user credentials.  Linux offers the API for obtaining user
credentials via ancillary messages (i.e., out of band/control messages
that are bundled together with a normal message).  To retrieve the security 
context, the application first indicates to the kernel such desire by 
setting the SO_PASSSEC option via getsockopt.  Then the application 
retrieves the security context using the auxiliary data mechanism.  

An example server application for Unix datagram socket should look like this:

toggle = 1;
toggle_len = sizeof(toggle);

setsockopt(sockfd, SOL_SOCKET, SO_PASSSEC, &toggle, &toggle_len);
recvmsg(sockfd, &msg_hdr, 0);
if (msg_hdr.msg_controllen > sizeof(struct cmsghdr)) {
    cmsg_hdr = CMSG_FIRSTHDR(&msg_hdr);
    if (cmsg_hdr->cmsg_len <= CMSG_LEN(sizeof(scontext)) &&
        cmsg_hdr->cmsg_level == SOL_SOCKET &&
        cmsg_hdr->cmsg_type == SCM_SECURITY) {
        memcpy(&scontext, CMSG_DATA(cmsg_hdr), sizeof(scontext));
    }
}

sock_setsockopt is enhanced with a new socket option SOCK_PASSSEC to allow
a server socket to receive security context of the peer.  

Testing:

We have tested the patch by setting up Unix datagram client and server
applications.  We verified that the server can retrieve the security context 
using the auxiliary data mechanism of recvmsg.


---

 include/asm-alpha/socket.h          |    1 
 include/asm-arm/socket.h            |    1 
 include/asm-arm26/socket.h          |    1 
 include/asm-cris/socket.h           |    1 
 include/asm-frv/socket.h            |    1 
 include/asm-h8300/socket.h          |    1 
 include/asm-i386/socket.h           |    1 
 include/asm-ia64/socket.h           |    1 
 include/asm-m32r/socket.h           |    1 
 include/asm-m68k/socket.h           |    1 
 include/asm-mips/socket.h           |    1 
 include/asm-parisc/socket.h         |    1 
 include/asm-powerpc/socket.h        |    1 
 include/asm-s390/socket.h           |    1 
 include/asm-sh/socket.h             |    1 
 include/asm-sparc/socket.h          |    1 
 include/asm-sparc64/socket.h        |    1 
 include/asm-v850/socket.h           |    1 
 include/asm-x86_64/socket.h         |    1 
 include/asm-xtensa/socket.h         |    1 
 include/linux/net.h                 |    1 
 include/linux/selinux.h             |  104 ++++++++++++++++++++++++++++++++++++
 include/net/af_unix.h               |    2 
 include/net/scm.h                   |   13 ++++
 net/core/sock.c                     |   11 +++
 net/unix/af_unix.c                  |    2 
 security/selinux/Makefile           |    2 
 security/selinux/exports.c          |   52 ++++++++++++++++++
 security/selinux/hooks.c            |   40 +++++++++----
 security/selinux/include/security.h |    7 ++
 security/selinux/ss/services.c      |    4 -
 31 files changed, 240 insertions(+), 18 deletions(-)

diff -puN include/asm-i386/socket.h~lsm-secpeer-unix include/asm-i386/socket.h
--- linux-2.6.17-rc1/include/asm-i386/socket.h~lsm-secpeer-unix 2006-04-03 
18:19:47.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/include/asm-i386/socket.h  2006-04-03 
18:20:46.000000000 -0400
@@ -48,5 +48,6 @@
 #define SO_ACCEPTCONN          30
 
 #define SO_PEERSEC             31
+#define SO_PASSSEC             34
 
 #endif /* _ASM_SOCKET_H */
diff -puN include/asm-x86_64/socket.h~lsm-secpeer-unix 
include/asm-x86_64/socket.h
--- linux-2.6.17-rc1/include/asm-x86_64/socket.h~lsm-secpeer-unix       
2006-04-03 18:19:47.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/include/asm-x86_64/socket.h        2006-04-03 
18:20:46.000000000 -0400
@@ -48,5 +48,6 @@
 #define SO_ACCEPTCONN          30
 
 #define SO_PEERSEC             31
+#define SO_PASSSEC             34
 
 #endif /* _ASM_SOCKET_H */
diff -puN include/asm-ia64/socket.h~lsm-secpeer-unix include/asm-ia64/socket.h
--- linux-2.6.17-rc1/include/asm-ia64/socket.h~lsm-secpeer-unix 2006-04-03 
18:19:47.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/include/asm-ia64/socket.h  2006-04-03 
18:20:46.000000000 -0400
@@ -57,5 +57,6 @@
 #define SO_ACCEPTCONN          30
 
 #define SO_PEERSEC             31
+#define SO_PASSSEC             34
 
 #endif /* _ASM_IA64_SOCKET_H */
diff -puN include/asm-powerpc/socket.h~lsm-secpeer-unix 
include/asm-powerpc/socket.h
--- linux-2.6.17-rc1/include/asm-powerpc/socket.h~lsm-secpeer-unix      
2006-04-03 18:19:47.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/include/asm-powerpc/socket.h       2006-04-03 
18:20:46.000000000 -0400
@@ -55,5 +55,6 @@
 #define SO_ACCEPTCONN          30
 
 #define SO_PEERSEC             31
+#define SO_PASSSEC             34
 
 #endif /* _ASM_POWERPC_SOCKET_H */
diff -puN include/asm-h8300/socket.h~lsm-secpeer-unix include/asm-h8300/socket.h
--- linux-2.6.17-rc1/include/asm-h8300/socket.h~lsm-secpeer-unix        
2006-04-03 18:19:47.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/include/asm-h8300/socket.h 2006-04-03 
18:20:46.000000000 -0400
@@ -48,5 +48,6 @@
 #define SO_ACCEPTCONN          30
 
 #define SO_PEERSEC             31
+#define SO_PASSSEC             34
 
 #endif /* _ASM_SOCKET_H */
diff -puN include/asm-s390/socket.h~lsm-secpeer-unix include/asm-s390/socket.h
--- linux-2.6.17-rc1/include/asm-s390/socket.h~lsm-secpeer-unix 2006-04-03 
18:19:47.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/include/asm-s390/socket.h  2006-04-03 
18:20:46.000000000 -0400
@@ -56,5 +56,6 @@
 #define SO_ACCEPTCONN          30
 
 #define SO_PEERSEC             31
+#define SO_PASSSEC             34
 
 #endif /* _ASM_SOCKET_H */
diff -puN include/asm-mips/socket.h~lsm-secpeer-unix include/asm-mips/socket.h
--- linux-2.6.17-rc1/include/asm-mips/socket.h~lsm-secpeer-unix 2006-04-03 
18:19:47.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/include/asm-mips/socket.h  2006-04-03 
18:20:46.000000000 -0400
@@ -69,6 +69,7 @@ To add: #define SO_REUSEPORT 0x0200   /* A
 #define SO_PEERSEC             30
 #define SO_SNDBUFFORCE         31
 #define SO_RCVBUFFORCE         33
+#define SO_PASSSEC             34
 
 #ifdef __KERNEL__
 
diff -puN include/asm-alpha/socket.h~lsm-secpeer-unix include/asm-alpha/socket.h
--- linux-2.6.17-rc1/include/asm-alpha/socket.h~lsm-secpeer-unix        
2006-04-03 18:19:47.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/include/asm-alpha/socket.h 2006-04-03 
18:20:46.000000000 -0400
@@ -51,6 +51,7 @@
 #define SCM_TIMESTAMP          SO_TIMESTAMP
 
 #define SO_PEERSEC             30
+#define SO_PASSSEC             31
 
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION             19
diff -puN include/asm-v850/socket.h~lsm-secpeer-unix include/asm-v850/socket.h
--- linux-2.6.17-rc1/include/asm-v850/socket.h~lsm-secpeer-unix 2006-04-03 
18:19:47.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/include/asm-v850/socket.h  2006-04-03 
18:20:46.000000000 -0400
@@ -48,5 +48,6 @@
 #define SO_ACCEPTCONN          30
 
 #define SO_PEERSEC             31
+#define SO_PASSSEC             34
 
 #endif /* __V850_SOCKET_H__ */
diff -puN include/asm-sh/socket.h~lsm-secpeer-unix include/asm-sh/socket.h
--- linux-2.6.17-rc1/include/asm-sh/socket.h~lsm-secpeer-unix   2006-04-03 
18:19:47.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/include/asm-sh/socket.h    2006-04-03 
18:20:46.000000000 -0400
@@ -48,5 +48,6 @@
 #define SO_ACCEPTCONN          30
 
 #define SO_PEERSEC             31
+#define SO_PASSSEC             34
 
 #endif /* __ASM_SH_SOCKET_H */
diff -puN include/asm-m68k/socket.h~lsm-secpeer-unix include/asm-m68k/socket.h
--- linux-2.6.17-rc1/include/asm-m68k/socket.h~lsm-secpeer-unix 2006-04-03 
18:19:47.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/include/asm-m68k/socket.h  2006-04-03 
18:20:46.000000000 -0400
@@ -48,5 +48,6 @@
 #define SO_ACCEPTCONN          30
 
 #define SO_PEERSEC             31
+#define SO_PASSSEC             34
 
 #endif /* _ASM_SOCKET_H */
diff -puN include/asm-arm/socket.h~lsm-secpeer-unix include/asm-arm/socket.h
--- linux-2.6.17-rc1/include/asm-arm/socket.h~lsm-secpeer-unix  2006-04-03 
18:19:47.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/include/asm-arm/socket.h   2006-04-03 
18:20:46.000000000 -0400
@@ -48,5 +48,6 @@
 #define SO_ACCEPTCONN          30
 
 #define SO_PEERSEC             31
+#define SO_PASSSEC             34
 
 #endif /* _ASM_SOCKET_H */
diff -puN include/asm-cris/socket.h~lsm-secpeer-unix include/asm-cris/socket.h
--- linux-2.6.17-rc1/include/asm-cris/socket.h~lsm-secpeer-unix 2006-04-03 
18:19:47.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/include/asm-cris/socket.h  2006-04-03 
18:20:46.000000000 -0400
@@ -50,6 +50,7 @@
 #define SO_ACCEPTCONN          30
 
 #define SO_PEERSEC             31
+#define SO_PASSSEC             34
 
 #endif /* _ASM_SOCKET_H */
 
diff -puN include/asm-arm26/socket.h~lsm-secpeer-unix include/asm-arm26/socket.h
--- linux-2.6.17-rc1/include/asm-arm26/socket.h~lsm-secpeer-unix        
2006-04-03 18:19:47.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/include/asm-arm26/socket.h 2006-04-03 
18:20:46.000000000 -0400
@@ -48,5 +48,6 @@
 #define SO_ACCEPTCONN          30
 
 #define SO_PEERSEC             31
+#define SO_PASSSEC             34
 
 #endif /* _ASM_SOCKET_H */
diff -puN include/asm-frv/socket.h~lsm-secpeer-unix include/asm-frv/socket.h
--- linux-2.6.17-rc1/include/asm-frv/socket.h~lsm-secpeer-unix  2006-04-03 
18:19:47.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/include/asm-frv/socket.h   2006-04-03 
18:20:46.000000000 -0400
@@ -48,6 +48,7 @@
 #define SO_ACCEPTCONN          30
 
 #define SO_PEERSEC             31
+#define SO_PASSSEC             34
 
 #endif /* _ASM_SOCKET_H */
 
diff -puN include/asm-xtensa/socket.h~lsm-secpeer-unix 
include/asm-xtensa/socket.h
--- linux-2.6.17-rc1/include/asm-xtensa/socket.h~lsm-secpeer-unix       
2006-04-03 18:19:47.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/include/asm-xtensa/socket.h        2006-04-03 
18:20:46.000000000 -0400
@@ -59,5 +59,6 @@
 
 #define SO_ACCEPTCONN          30
 #define SO_PEERSEC             31
+#define SO_PASSSEC             34
 
 #endif /* _XTENSA_SOCKET_H */
diff -puN include/asm-m32r/socket.h~lsm-secpeer-unix include/asm-m32r/socket.h
--- linux-2.6.17-rc1/include/asm-m32r/socket.h~lsm-secpeer-unix 2006-04-03 
18:19:48.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/include/asm-m32r/socket.h  2006-04-03 
18:20:46.000000000 -0400
@@ -48,5 +48,6 @@
 #define SO_ACCEPTCONN          30
 
 #define SO_PEERSEC             31
+#define SO_PASSSEC             34
 
 #endif /* _ASM_M32R_SOCKET_H */
diff -puN include/asm-parisc/socket.h~lsm-secpeer-unix 
include/asm-parisc/socket.h
--- linux-2.6.17-rc1/include/asm-parisc/socket.h~lsm-secpeer-unix       
2006-04-03 18:19:48.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/include/asm-parisc/socket.h        2006-04-03 
18:20:46.000000000 -0400
@@ -48,5 +48,6 @@
 #define SO_ACCEPTCONN          0x401c
 
 #define SO_PEERSEC             0x401d
+#define SO_PASSSEC             0x401e
 
 #endif /* _ASM_SOCKET_H */
diff -puN include/asm-sparc/socket.h~lsm-secpeer-unix include/asm-sparc/socket.h
--- linux-2.6.17-rc1/include/asm-sparc/socket.h~lsm-secpeer-unix        
2006-04-07 19:21:24.286406168 -0400
+++ linux-2.6.17-rc1-cxzhang/include/asm-sparc/socket.h 2006-04-07 
19:21:03.896505904 -0400
@@ -48,6 +48,7 @@
 #define SCM_TIMESTAMP          SO_TIMESTAMP
 
 #define SO_PEERSEC             0x001e
+#define SO_PASSSEC             0x001f
 
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION             0x5001
diff -puN include/asm-sparc64/socket.h~lsm-secpeer-unix 
include/asm-sparc64/socket.h
--- linux-2.6.17-rc1/include/asm-sparc64/socket.h~lsm-secpeer-unix      
2006-04-07 19:19:50.788619992 -0400
+++ linux-2.6.17-rc1-cxzhang/include/asm-sparc64/socket.h       2006-04-07 
19:19:24.046685384 -0400
@@ -48,6 +48,7 @@
 #define SCM_TIMESTAMP          SO_TIMESTAMP
 
 #define SO_PEERSEC             0x001e
+#define SO_PASSSEC             0x001f
 
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION             0x5001
diff -puN include/linux/net.h~lsm-secpeer-unix include/linux/net.h
--- linux-2.6.17-rc1/include/linux/net.h~lsm-secpeer-unix       2006-04-03 
18:19:48.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/include/linux/net.h        2006-04-03 
18:20:46.000000000 -0400
@@ -62,6 +62,7 @@ typedef enum {
 #define SOCK_ASYNC_WAITDATA    1
 #define SOCK_NOSPACE           2
 #define SOCK_PASSCRED          3
+#define SOCK_PASSSEC           4
 
 #ifndef ARCH_HAS_SOCKET_TYPES
 /**
diff -puN include/net/af_unix.h~lsm-secpeer-unix include/net/af_unix.h
--- linux-2.6.17-rc1/include/net/af_unix.h~lsm-secpeer-unix     2006-04-03 
18:19:48.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/include/net/af_unix.h      2006-04-03 
18:20:46.000000000 -0400
@@ -54,10 +54,12 @@ struct unix_address {
 struct unix_skb_parms {
        struct ucred            creds;          /* Skb credentials      */
        struct scm_fp_list      *fp;            /* Passed files         */
+       u32                     sid;            /* Security ID          */
 };
 
 #define UNIXCB(skb)    (*(struct unix_skb_parms*)&((skb)->cb))
 #define UNIXCREDS(skb) (&UNIXCB((skb)).creds)
+#define UNIXSID(skb)   (&UNIXCB((skb)).sid)
 
 #define unix_state_rlock(s)    spin_lock(&unix_sk(s)->lock)
 #define unix_state_runlock(s)  spin_unlock(&unix_sk(s)->lock)
diff -puN include/net/scm.h~lsm-secpeer-unix include/net/scm.h
--- linux-2.6.17-rc1/include/net/scm.h~lsm-secpeer-unix 2006-04-03 
18:19:48.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/include/net/scm.h  2006-04-06 14:26:02.000000000 
-0400
@@ -3,6 +3,8 @@
 
 #include <linux/limits.h>
 #include <linux/net.h>
+#include <linux/security.h>
+#include <linux/selinux.h>
 
 /* Well, we should have at least one descriptor open
  * to accept passed FDs 8)
@@ -19,6 +21,7 @@ struct scm_cookie
 {
        struct ucred            creds;          /* Skb credentials      */
        struct scm_fp_list      *fp;            /* Passed files         */
+       u32                     sid;            /* Passed security ID   */
        unsigned long           seq;            /* Connection seqno     */
 };
 
@@ -42,6 +45,7 @@ static __inline__ int scm_send(struct so
        scm->creds.gid = p->gid;
        scm->creds.pid = p->tgid;
        scm->fp = NULL;
+       selinux_sock_ctxid(sock, &scm->sid);
        scm->seq = 0;
        if (msg->msg_controllen <= 0)
                return 0;
@@ -51,6 +55,9 @@ static __inline__ int scm_send(struct so
 static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
                                struct scm_cookie *scm, int flags)
 {
+       char *scontext;
+       int scontext_len, err;
+
        if (!msg->msg_control)
        {
                if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp)
@@ -62,6 +69,12 @@ static __inline__ void scm_recv(struct s
        if (test_bit(SOCK_PASSCRED, &sock->flags))
                put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), 
&scm->creds);
 
+       if (test_bit(SOCK_PASSSEC, &sock->flags)) {
+               err = selinux_id_to_ctx(scm->sid, &scontext, &scontext_len);
+               if (!err)
+                       put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, scontext_len, 
scontext);
+       }
+
        if (!scm->fp)
                return;
        
diff -puN net/core/sock.c~lsm-secpeer-unix net/core/sock.c
--- linux-2.6.17-rc1/net/core/sock.c~lsm-secpeer-unix   2006-04-03 
18:19:48.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/net/core/sock.c    2006-04-03 18:20:46.000000000 
-0400
@@ -565,6 +565,13 @@ set_rcvbuf:
                        ret = -ENONET;
                        break;
 
+               case SO_PASSSEC:
+                       if (valbool)
+                               set_bit(SOCK_PASSSEC, &sock->flags);
+                       else
+                               clear_bit(SOCK_PASSSEC, &sock->flags);
+                       break;
+
                /* We implement the SO_SNDLOWAT etc to
                   not be settable (1003.1g 5.3) */
                default:
@@ -723,6 +730,10 @@ int sock_getsockopt(struct socket *sock,
                        v.val = sk->sk_state == TCP_LISTEN;
                        break;
 
+               case SO_PASSSEC:
+                       v.val = test_bit(SOCK_PASSSEC, &sock->flags) ? 1 : 0;
+                       break;
+
                case SO_PEERSEC:
                        return security_socket_getpeersec_stream(sock, optval, 
optlen, len);
 
diff -puN net/unix/af_unix.c~lsm-secpeer-unix net/unix/af_unix.c
--- linux-2.6.17-rc1/net/unix/af_unix.c~lsm-secpeer-unix        2006-04-03 
18:19:48.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/net/unix/af_unix.c 2006-04-03 18:20:46.000000000 
-0400
@@ -1290,6 +1290,7 @@ static int unix_dgram_sendmsg(struct kio
        memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
        if (siocb->scm->fp)
                unix_attach_fds(siocb->scm, skb);
+       memcpy(UNIXSID(skb), &siocb->scm->sid, sizeof(u32));
 
        skb->h.raw = skb->data;
        err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
@@ -1570,6 +1571,7 @@ static int unix_dgram_recvmsg(struct kio
                memset(&tmp_scm, 0, sizeof(tmp_scm));
        }
        siocb->scm->creds = *UNIXCREDS(skb);
+       siocb->scm->sid   = *UNIXSID(skb);
 
        if (!(flags & MSG_PEEK))
        {
diff -puN security/selinux/Makefile~lsm-secpeer-unix security/selinux/Makefile
--- linux-2.6.17-rc1/security/selinux/Makefile~lsm-secpeer-unix 2006-04-04 
18:30:47.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/security/selinux/Makefile  2006-04-04 
18:31:29.000000000 -0400
@@ -4,7 +4,7 @@
 
 obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/
 
-selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o
+selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o exports.o
 
 selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
 
diff -puN /dev/null security/selinux/exports.c
--- /dev/null   2006-01-22 15:03:06.693899048 -0500
+++ linux-2.6.17-rc1-cxzhang/security/selinux/exports.c 2006-04-06 
14:29:28.000000000 -0400
@@ -0,0 +1,52 @@
+/*
+ * SELinux services exported to the rest of the kernel.
+ *
+ * Author: James Morris <[EMAIL PROTECTED]>
+ *
+ * Copyright (C) 2005 Red Hat, Inc., James Morris <[EMAIL PROTECTED]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/selinux.h>
+
+#include "security.h"
+
+extern int ss_initialized;
+
+int selinux_available(void)
+{
+       return ss_initialized;
+}
+
+void selinux_sk_ctxid(struct sock *sk, u32 *ctxid)
+{
+       *ctxid = 0;
+       security_sk_info(sk, ctxid, NULL);
+}
+
+void selinux_sock_ctxid(struct socket *sock, u32 *ctxid)
+{
+       *ctxid = 0;
+       security_sock_info(sock, ctxid, NULL);
+}
+
+int selinux_ctx_to_id(const char *ctx, u32 *ctxid)
+{
+       return security_context_to_sid(ctx, strlen(ctx), ctxid);
+}
+
+int selinux_id_to_ctx(u32 ctxid, char **ctx, u32 *ctxlen)
+{
+       return security_sid_to_context(ctxid, ctx, ctxlen);
+}
+
+EXPORT_SYMBOL_GPL(selinux_available);
+EXPORT_SYMBOL_GPL(selinux_sk_ctxid);
+EXPORT_SYMBOL_GPL(selinux_sock_ctxid);
+EXPORT_SYMBOL_GPL(selinux_ctx_to_id);
+EXPORT_SYMBOL_GPL(selinux_id_to_ctx);
diff -puN security/selinux/hooks.c~lsm-secpeer-unix security/selinux/hooks.c
--- linux-2.6.17-rc1/security/selinux/hooks.c~lsm-secpeer-unix  2006-04-04 
18:36:25.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/security/selinux/hooks.c   2006-04-06 
14:35:14.000000000 -0400
@@ -3212,6 +3212,29 @@ static int selinux_socket_unix_may_send(
        return 0;
 }
 
+/* Retrieve security info. on sock */
+void security_sock_info(struct socket *sock, u32 *sid, u16 *class)
+{
+       if (sock) {
+               struct inode *inode;
+               inode = SOCK_INODE(sock);
+               if (inode) {
+                       struct inode_security_struct *isec;
+                       isec = inode->i_security;
+                       if (sid)
+                               *sid = isec->sid;
+                       if (class)
+                               *class = isec->sclass;
+               }
+       }
+}
+
+/* Caller must hold sk_callback_lock */
+void security_sk_info(struct sock *sk, u32 *sid, u16 *class)
+{
+       security_sock_info(sk->sk_socket, sid, class);
+}
+
 static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
        u16 family;
@@ -3220,7 +3243,6 @@ static int selinux_socket_sock_rcv_skb(s
        u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0;
        u32 sock_sid = 0;
        u16 sock_class = 0;
-       struct socket *sock;
        struct net_device *dev;
        struct avc_audit_data ad;
 
@@ -3232,19 +3254,9 @@ static int selinux_socket_sock_rcv_skb(s
        if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP))
                family = PF_INET;
 
-       read_lock_bh(&sk->sk_callback_lock);
-       sock = sk->sk_socket;
-       if (sock) {
-               struct inode *inode;
-               inode = SOCK_INODE(sock);
-               if (inode) {
-                       struct inode_security_struct *isec;
-                       isec = inode->i_security;
-                       sock_sid = isec->sid;
-                       sock_class = isec->sclass;
-               }
-       }
-       read_unlock_bh(&sk->sk_callback_lock);
+       read_lock_bh(&sk->sk_callback_lock);
+       security_sk_info(sk, &sock_sid, &sock_class);
+       read_unlock_bh(&sk->sk_callback_lock);
        if (!sock_sid)
                goto out;
 
diff -puN security/selinux/include/security.h~lsm-secpeer-unix 
security/selinux/include/security.h
--- linux-2.6.17-rc1/security/selinux/include/security.h~lsm-secpeer-unix       
2006-04-04 18:36:25.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/security/selinux/include/security.h        
2006-04-06 14:41:30.000000000 -0400
@@ -63,7 +63,7 @@ int security_change_sid(u32 ssid, u32 ts
 int security_sid_to_context(u32 sid, char **scontext,
        u32 *scontext_len);
 
-int security_context_to_sid(char *scontext, u32 scontext_len,
+int security_context_to_sid(const char *scontext, u32 scontext_len,
        u32 *out_sid);
 
 int security_context_to_sid_default(char *scontext, u32 scontext_len, u32 
*out_sid, u32 def_sid);
@@ -96,5 +96,10 @@ int security_fs_use(const char *fstype, 
 int security_genfs_sid(const char *fstype, char *name, u16 sclass,
        u32 *sid);
 
+struct sock;
+struct socket;
+void security_sk_info(struct sock *sk, u32 *sid, u16 *class);
+void security_sock_info(struct socket *sock, u32 *sid, u16 *class);
+
 #endif /* _SELINUX_SECURITY_H_ */
 
diff -puN security/selinux/ss/services.c~lsm-secpeer-unix 
security/selinux/ss/services.c
--- linux-2.6.17-rc1/security/selinux/ss/services.c~lsm-secpeer-unix    
2006-04-04 18:36:25.000000000 -0400
+++ linux-2.6.17-rc1-cxzhang/security/selinux/ss/services.c     2006-04-04 
18:36:45.000000000 -0400
@@ -618,7 +618,7 @@ out:
 
 }
 
-static int security_context_to_sid_core(char *scontext, u32 scontext_len, u32 
*sid, u32 def_sid)
+static int security_context_to_sid_core(const char *scontext, u32 
scontext_len, u32 *sid, u32 def_sid)
 {
        char *scontext2;
        struct context context;
@@ -744,7 +744,7 @@ out:
  * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
  * memory is available, or 0 on success.
  */
-int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
+int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid)
 {
        return security_context_to_sid_core(scontext, scontext_len,
                                            sid, SECSID_NULL);
diff -puN /dev/null include/linux/selinux.h
--- /dev/null   2006-01-22 15:03:06.693899048 -0500
+++ linux-2.6.17-rc1-cxzhang/include/linux/selinux.h    2006-04-07 
12:35:49.000000000 -0400
@@ -0,0 +1,104 @@
+/*
+ * SELinux services exported to the rest of the kernel.
+ *
+ * Author: James Morris <[EMAIL PROTECTED]>
+ *
+ * Copyright (C) 2005 Red Hat, Inc., James Morris <[EMAIL PROTECTED]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ */
+#ifndef _LINUX_SELINUX_H
+#define _LINUX_SELINUX_H
+
+#ifdef CONFIG_SECURITY_SELINUX
+
+struct sock;
+struct socket;
+
+/**
+ *     selinux_available - check if SELinux is available for use.
+ *
+ *     Returns true if configured, enabled, not disabled and policy loaded.
+ */
+int selinux_available(void);
+
+/**
+ *     selinux_sk_ctxid - determine a context ID for an sk.
+ *     @sk: the sk object
+ *     @ctxid: ID value returned via this
+ *
+ *     On return, ctxid will contain an ID for the context, with a value
+ *     of zero to indicate no ID could be determined.  Otherwise, this value
+ *     should only be used opaquely.
+ *
+ *     Caller must hold sk_callback_lock.
+ */
+void selinux_sk_ctxid(struct sock *sk, u32 *ctxid);
+
+/**
+ *     selinux_sock_ctxid - determine a context ID for a socket.
+ *     @sock: the socket object
+ *     @ctxid: ID value returned via this
+ *
+ *     On return, ctxid will contain an ID for the context, with a value
+ *     of zero to indicate no ID could be determined.  Otherwise, this value
+ *     should only be used opaquely.
+ */
+void selinux_sock_ctxid(struct socket *sock, u32 *ctxid);
+
+/**
+ *     selinux_ctx_to_id - map a security context string to an ID
+ *     @ctx: the security context string to be mapped
+ *     @ctxid: ID value returned via this.
+ *
+ *     Returns 0 if successful, with the ID stored in ctxid.  A value
+ *     of zero for the ctxid indicates no ID could be determined (but
+ *     no error occurred).  Otherwise, this value should only be used
+ *     opaquely (e.g. compare with value from selinux_sk_ctxid())
+ */
+int selinux_ctx_to_id(const char *ctx, u32 *ctxid);
+
+/**
+ *     selinux_id_to_ctx - map a security context ID to a string
+ *     @ctxid: security context ID to be converted.
+ *     @ctx: address of context string to be returned
+ *     @ctxlen: length of returned context string.
+ *
+ *     Returns 0 if successful, -errno if not.  On success, the context
+ *     string will be allocated internally, and the caller must call
+ *     kfree() on it after use.
+ */
+int selinux_id_to_ctx(u32 ctxid, char **ctx, u32 *ctxlen);
+
+#else
+
+static inline int selinux_available(void)
+{
+       return 0;
+}
+
+static inline void selinux_sk_ctxid(struct sock *sk, u32 *ctxid)
+{
+       *ctxid = 0;
+}
+
+static inline void selinux_sock_ctxid(struct socket *sock, u32 *ctxid)
+{
+       *ctxid = 0;
+}
+
+static inline int selinux_ctx_to_id(const char *ctx, u32 *ctxid)
+{
+       *ctxid = 0;
+       return -ENOTSUPP;
+}
+
+static inline int selinux_id_to_ctx(u32 ctxid, char **ctx, u32 *ctxlen)
+{
+       return -ENOTSUPP;
+}
+#endif /* CONFIG_SECURITY_SELINUX */
+
+#endif /* _LINUX_SELINUX_H */
_
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to