Re: [PATCH 1/1] Add post accept()/recvmsg() hooks.
On Tuesday, July 3 2007 8:07:45 am Tetsuo Handa wrote: > diff -ur a/include/linux/security.h b/include/linux/security.h > --- a/include/linux/security.h2007-07-03 10:07:14.0 +0900 > +++ b/include/linux/security.h2007-07-03 13:21:20.581744544 +0900 > @@ -745,6 +745,16 @@ > * @sock contains the listening socket structure. > * @newsock contains the newly created server socket for connection. > * Return 0 if permission is granted. > + * @socket_pre_accept: > + * Check peer's address after accepting a new connection but > + * before making that connection visible to userland. > + * This hook is intended for filtering connections from unwanted peers. > + * The connection will be aborted if this hook returns nonzero. > + * @sock contains the listening socket structure. > + * @newsock contains the newly created server socket for connection. > + * @address contains the address of remote endpoint. > + * @addrlen contains the length of address. > + * Return 0 if permission is granted. ... and below ... > diff -ur a/net/socket.c b/net/socket.c > --- a/net/socket.c2007-07-03 10:07:16.0 +0900 > +++ b/net/socket.c2007-07-03 13:23:53.055565000 +0900 > @@ -1426,6 +1437,11 @@ > if (err < 0) > goto out_fd; > > + /* Filter connections from unwanted peers like TCP Wrapper. */ > + err = security_socket_pre_accept(sock, newsock); > + if (err) > + goto out_fd; > + > if (upeer_sockaddr) { > if (newsock->ops->getname(newsock, (struct sockaddr *)address, > &len, 2) < 0) { I believe the existing security_inet_conn_request() LSM hook should allow you to do what you want. Adding another hook _after_ the inbound connection has been accepted is probably a bad idea. > diff -ur a/include/linux/security.h b/include/linux/security.h > --- a/include/linux/security.h2007-07-03 10:07:14.0 +0900 > +++ b/include/linux/security.h2007-07-03 13:21:20.581744544 +0900 > @@ -763,6 +773,14 @@ > * @size contains the size of message structure. > * @flags contains the operational flags. > * Return 0 if permission is granted. > + * @socket_post_recvmsg: > + * Check peer's address after receiving a message from a socket. > + * This hook is intended for filtering messages from unwanted peers. > + * @sock contains the socket structure. > + * @msg contains the message structure. > + * @size contains the size of message structure. > + * @flags contains the operational flags. > + * Return 0 if permission is granted. > * @socket_getsockname: > * Check permission before the local address (name) of the socket object > * @sock is retrieved. ... and below ... > diff -ur a/net/socket.c b/net/socket.c > --- a/net/socket.c2007-07-03 10:07:16.0 +0900 > +++ b/net/socket.c2007-07-03 13:23:53.055565000 +0900 > @@ -651,6 +651,17 @@ > ret = __sock_recvmsg(&iocb, sock, msg, size, flags); > if (-EIOCBQUEUED == ret) > ret = wait_on_sync_kiocb(&iocb); > + /* > + * Filter messages from unwanted peers. > + * To be exact, this hook can't filter messages, > + * this hook just returns an error code. > + * Do we have to keep userland buffer unchanged until this hook? > + */ > + if (ret >= 0) { > + int err = security_socket_post_recvmsg(sock, msg, size, flags); > + if (err) > + ret = err; > + } > return ret; > } Is there some reason why you can't use security_socket_recvmsg()? Also, don't forget that there are many other ways to read a network socket than just recvmsg(). -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/1] Add post accept()/recvmsg() hooks.
On Thursday, July 5 2007 10:01:59 pm Tetsuo Handa wrote: > Paul Moore wrote: > > I believe the existing security_inet_conn_request() LSM hook should allow > > you to do what you want. Adding another hook _after_ the inbound > > connection has been accepted is probably a bad idea. > > Unfortunately, security_inet_conn_request() doesn't allow blocking > operation. I want to sleep inside this hook because I want to use > interactive operation by asking users whether to accept this connection or > not. Perhaps you could move the security_post_accept() hook further up and add a return value? I do not see any current in-tree users of the hook and I imagine moving it up would actually make the existing hook a bit more useful in general. > > Is there some reason why you can't use security_socket_recvmsg()? Also, > > don't forget that there are many other ways to read a network socket than > > just recvmsg(). > > security_socket_recvmsg() is called before retrieving a message. > I want a hook that is called after retrieving a message > because I want to use IP address and port number. > But it seems that there are cases (recvmsg() and read()?) where > __sock_recvmsg() is called with msg->name == NULL and msg->msg_namelen == 0 > that makes what I want to do impossible. > To make IP address and port number always available, > some more changes (that are not related with LSM) are needed. In the existing security_socket_recvmsg() hook you could peek at the top of the socket's receive queue and determine all of the information you would want to know to make your access decision. Granted, it still might be a bit racy if you have two threads reading from the same socket (maybe there is a lock there, I would have to check it further) but it can't be any worse then performing an access check _after_ the fact ... -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/1] Add post accept()/recvmsg() hooks.
On Friday, July 6 2007 10:59:49 am Tetsuo Handa wrote: > > In the existing security_socket_recvmsg() hook you could peek at the top > > of the socket's receive queue and determine all of the information you > > would want to know to make your access decision. Granted, it still might > > be a bit racy if you have two threads reading from the same socket (maybe > > there is a lock there, I would have to check it further) but it can't be > > any worse then performing an access check _after_ the fact ... > > I think dequeuing this message is needed, or programs that call recv() like > > while (1) { > FD_SET(fd, &rfds); > select(fd + 1, &rfds, NULL, NULL, NULL); > recv(fd, buffer, sizeof(buffer), 0); > } > > will begin meaningless infinite loop. Okay, so remove the first message from the queue when your LSM declares a denial. > A proper way to avoid this loop will be "not to return ready answer for > select()". But to do so, I will need modifications in lower layer where it > is not allowed to sleep. I'm not sure this would be the "proper" way to fix the problem, as you would still collect data in the socket's receive buffer, you just wouldn't let the application know about it. Thinking about the implementation also makes me nervous as I can't think of a clean/sane way of doing it; maybe you can but I'm still not sure that is justification for the change. Thinking about your problem (personal firewall) a bit more I can't help but wonder if your solution would be better implemented as a netfilter module? Or maybe in userspace using the netfilter userspace queue feature? -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/1] Add post accept()/recvmsg() hooks.
On Friday, July 6 2007 1:25:22 pm Tetsuo Handa wrote: > So, recv() returning -EPERM after dequing this message is acceptable? Maybe :) I would suggest sending a patchset to the list with both the LSM interface change patch (the one we have been discussing) as well as your actual LSM/personal-firewall patch. You may also want to CC other relevant lists (based on this discussion netdev comes to mind) on your posting as they should probably review your suggested changes too. -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC][PATCH] Simplified mandatory access control kernel implementation
*/ + return smack_net_ambient; + } + /* +* Get the categories, if any +*/ + if ((sap->flags & NETLBL_SECATTR_MLS_CAT) != 0) + for (pcat = -1;;) { + pcat = netlbl_secattr_catmap_walk(sap->mls_cat, pcat+1); + if (pcat < 0) + break; + smack_catset_bit(pcat, &smack); + } + /* +* If it is CIPSO using smack direct mapping +* we are already done. WeeHee. +*/ + if (sap->mls_lvl == SMACK_CIPSO_DIRECT) + return smack; + + /* +* Look it up in the supplied table if it is not a direct mapping. +*/ + for (scp = smack_cipso; scp != NULL; scp = scp->smk_next) + if (scp->smk_level == sap->mls_lvl && scp->smk_catset == smack) + return scp->smk_smack; The NetLabel caching mechanism can help make this a lot less painful, i.e. direct return of the correct "smack" instead of traversing an unordered linked list each time. +static ssize_t smk_write_cipso(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct smk_cipso_entry *scp; + smack_t mapsmack; + smack_t mapcatset; + int maplevel; + ssize_t rc = count; + char *data = NULL; + char *cp; + char *eolp; + char *linep; + int cat; + int i; + + smk_cipso_doi(); + + if (!capable(CAP_MAC_OVERRIDE)) + return -EPERM; + /* +* No partial writes. +*/ + if (*ppos != 0) + return -EINVAL; + /* +* Casey wonders about this number. +*/ + if ((count > 64 * 1024 * 1024) || (data = vmalloc(count + 1)) == NULL) + return -ENOMEM; I wonder about that number too. I realize it is always going to be hard to get rid of all those magic numbers, but at least put a nice comment there so we know the reasoning behind the value (saying it's a guess is okay for me) and ideally make it a constant/macro/#define somewhere. This applies to a few other places in the code too. +int smk_curacc(smack_t *obj_label, u32 mode) +{ + struct task_smack *tsp = current->security; + int rc; + + rc = smk_access(&tsp->smk_task, obj_label, mode); + if (rc == 0) + return 0; + + if (capable(CAP_MAC_OVERRIDE)) + return 0; + + return rc; +} I noticed a distinct lack of auditing in SMACK, the function above is a perfect example. I know Linux's auditing mechanism is "interesting", but you should probably make use of it for security related events. +/* + * Should access checks be done on each read or write? + * UNICOS and SELinux say yes. + * Trusted Solaris, Trusted Irix, and just about everyone else says no. + */ +static int smack_file_permission(struct file *file, int mask) +{ +#ifdef SMACKONREADWRITE + smack_t *fsp; + int rc; + + if (mask == 0) + return 0; + + fsp = (smack_t *)file->f_dentry->d_inode->i_security; + + rc = smk_curacc(fsp, mask); + return rc; +#else /* SMACKONREADWRITE */ + return 0; +#endif /* SMACKONREADWRITE */ +} Pick one, even if it's wrong :) +static int smack_task_to_sock(struct sock *sk, struct task_smack *tsp) +{ + struct netlbl_lsm_secattr secattr; + int rc; + + netlbl_secattr_init(&secattr); + smack_to_secattr(tsp->smk_out, tsp->smk_ipscheme, &secattr); + if (secattr.flags != 0) Please use the constants defined for the flag values in the NetLabel LSM security attributes; it makes life easier if for some freak reason we have to change them. For example, 0 == NETLBL_SECATTR_NONE. This applies to a few other places in the code too. I'm sure there will be more comments but these are the ones that jumped out at me. -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC][PATCH] Simplified mandatory access control kernel implementation
On Monday, July 16 2007 10:59:41 pm Casey Schaufler wrote: > --- Paul Moore <[EMAIL PROTECTED]> wrote: > > On Saturday, July 14 2007 5:47:38 pm Casey Schaufler wrote: > > +#include "../../net/netlabel/netlabel_domainhash.h" > > +#include > > + > > + {snip} > > + > > +static void smk_cipso_doi(void) > > +{ > > + int rc; > > + struct cipso_v4_doi *doip; > > + struct netlbl_dom_map *ndmp; > > + struct netlbl_audit audit_info; > > + > > + if (smk_cipso_doied != 0) > > + return; > > + smk_cipso_doied = 1; > > + > > + doip = kmalloc(sizeof(struct cipso_v4_doi), GFP_KERNEL); > > + if (doip == NULL) > > + panic("smack: Failed to initialize cipso DOI.\n"); > > + doip->map.std = NULL; > > + > > + ndmp = kmalloc(sizeof(struct netlbl_dom_map), GFP_KERNEL); > > + if (ndmp == NULL) > > + panic("smack: Failed to initialize cipso ndmp.\n"); > > + > > + doip->doi = SMACK_CIPSO_DOI; > > + doip->type = CIPSO_V4_MAP_PASS; > > + doip->tags[0] = CIPSO_V4_TAG_RBITMAP; > > + for (rc = 1; rc < CIPSO_V4_TAG_MAXCNT; rc++) > > + doip->tags[rc] = CIPSO_V4_TAG_INVALID; > > + > > + rc = cipso_v4_doi_add(doip); > > + printk("%s:%d add doi rc = %d\n", __FUNCTION__, __LINE__, rc); > > + > > + /* > > + rc = cipso_v4_doi_domhsh_add(doip, SMACK_CIPSO_DOMAIN_NAME); > > + printk("%s:%d hash doi rc = %d\n", __FUNCTION__, __LINE__, rc); > > +*/ > > + ndmp->domain = SMACK_CIPSO_DOMAIN_NAME; > > + ndmp->type = NETLBL_NLTYPE_CIPSOV4; > > + ndmp->type_def.cipsov4 = doip; > > + rc = netlbl_domhsh_add(ndmp, &audit_info); > > + printk("%s:%d hash doi rc = %d\n", __FUNCTION__, __LINE__, rc); > > +} > > > > If SMACK gets an OK for upstream we need to find a better solution than > > the above. The smk_cipso_doi() function pokes into too many NetLabel > > internals. > > > > The two obvious options are to rely on userspace (netlabel_tools) to > > configure NetLabel for SMACK, like SELinux, or to create a new NetLabel > > API for allowing LSMs to manipulate the NetLabel domain mapping. > > A userspace scheme is a non-starter, it goes against the project > goals of minimal dependence on helper applications. I would be happy > to work with you to create an appropriate API. All right, that's fair. For the time being just throw a comment in the code and we'll work on something. > > Also, any reason why you don't just use the NetLabel default domain > > mapping? > > Uh, only that I couldn't figure out how to go about doing so. If it > simplifies (there's that word again) things I'm all for it. I would > be happy to have my ignorance dispelled. Two things: 1. change "ndmp->domain = SMACK_CIPSO_DOMAIN_NAME" to "ndmp->domain = NULL" 2. change "netlbl_domhsh_add()" to "netlbl_domhsh_add_default()" If you want to get really nitpicky the second step is optional, but I'd prefer you use it in case we ever need to do something radically different for the default NetLabel domain mapping (it's really easy as they take the same arguments in the same order, just change the function name). > > +/* > > + * CIPSO domain information. > > + * Casey says that these may wind up being configurable > > + * at some point. > > + */ > > +#define SMACK_CIPSO_DOMAIN_NAME"SmackCIPSO" > > +#define SMACK_CIPSO_DOI3 > > +#define SMACK_CIPSO_DIRECT 250 /* Arbitrary and bad */ > > > > Yes, SMACK_CIPSO_DIRECT is bad. > > There has to be a cleaner solution than this, > > think harder ;) > > The cleanest solution is already in the code, where there's a 1:1 > mapping of Smack labels to Cipso level/catset maintained via > /smack/cipso, and set administratively. A purist can always set > this up to be complete. > > On the other hand, it has already been acknowledged that mapping one > set of CIPSO tags to another is necessary in some cases, for example > when one machine's bit 6 represents another's bits 2 and 3. My main complaint is the "magic number" of 250. Constants that are visible outside a subsystem make me very nervous, especially when they are "Arbitrary and bad". I understand the desire to have a direct mapping, that isn't my concern, my worry is how you specify to the other end that it is a direct mapping. > > +static smack_t smack_from_secattr(struct netlbl_lsm_secat
Re: [RFC][PATCH] Simplified mandatory access control kernel implementation
On Tuesday, July 17 2007 2:51:14 pm Casey Schaufler wrote: > --- Paul Moore <[EMAIL PROTECTED]> wrote: > > > > Also, any reason why you don't just use the NetLabel default domain > > > > mapping? > > > > > > Uh, only that I couldn't figure out how to go about doing so. If it > > > simplifies (there's that word again) things I'm all for it. I would > > > be happy to have my ignorance dispelled. > > > > Two things: > > > > 1. change "ndmp->domain = SMACK_CIPSO_DOMAIN_NAME" to "ndmp->domain = > > NULL" 2. change "netlbl_domhsh_add()" to "netlbl_domhsh_add_default()" > > > > If you want to get really nitpicky the second step is optional, but I'd > > prefer > > you use it in case we ever need to do something radically different for > > the default NetLabel domain mapping (it's really easy as they take the > > same arguments in the same order, just change the function name). > > I gave these changes a try. netlbl_domhsh_add_default() returns > -EEXIST and packets are not getting labeled. Is it possible that > the default domain has to be cached? Nope, but I forgot that you have to remove the existing default mapping first (the kernel creates a default unlabeled mapping at boot) ... you'll need to make a call to netlbl_domhsh_remove_default() first to get rid of the kernel's initial domain mapping. Sorry about that. -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC][PATCH] Simplified mandatory access control kernel implementation
On Thursday, July 19 2007 10:15:53 am James Morris wrote: > On Thu, 19 Jul 2007, Joshua Brindle wrote: > > > I also see an effort that's SELinux specific. Should be fun. > > > > The SELinux part is going to be a profile on top of the generic part so > > there shouldn't be any conflicts in the implementation. > > I wonder if it'd be worth setting up a mailing list specifically for this. > We currently have too much off-list discussion happening, and nowhere > really good to have it on-list. > > Thoughts? I like public discussion whenever possible and so far I haven't seen anything crop up that warrants private email. A public list might also help attract some warm bodies willing to write code ;) -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [TOMOYO 15/15] LSM expansion for TOMOYO Linux.
On Friday, August 24 2007 8:58:28 am Kentaro Takeda wrote: > LSM hooks for network accept and recv: >* socket_post_accept is modified to return int. This has been discussed several times on various lists and is not considered an acceptable solution to blocking incoming stream connection attempts. Please take a look at the existing LSM stream connection request hooks as well as how SELinux makes use of them. >* post_recv_datagram is added in skb_recv_datagram. Can you explain to me why this is not possible using the existing security_socket_sock_rcv_skb() LSM hook? -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [TOMOYO 15/15] LSM expansion for TOMOYO Linux.
On Tuesday, August 28 2007 6:39:13 am Tetsuo Handa wrote: > Hello. Hello. > Paul Moore wrote: > > >* post_recv_datagram is added in skb_recv_datagram. > > > > Can you explain to me why this is not possible using the existing > > security_socket_sock_rcv_skb() LSM hook? > > socket_sock_rcv_skb() is a hook for enqueue time. > I want a hook for dequeue time, because what TOMOYO Linux is doing is > not "whether a socket created by foo is permitted to pick up > an incoming packet from specific address/port" > but "whether bar is permitted to pick up > an incoming packet from specific address/port". > At the time of enqueue, I can't know who will pick up that packet. > > Same reason for socket_post_accept(). What TOMOYO Linux is doing is > not "whether a socket created by foo is permitted to accept > a connection request from specific address/port" > but "whether bar is permitted to accept > a connection request from specific address/port". > At the time of enqueue, I can't know who will pick up that request. I apologize for not recognizing your approach from our earlier discussion on the LSM mailing list in July. Unfortunately, I have the same objections to these changes that I did back then and from what I can recall of the discussion the rest of the kernel networking community agreed that these changes are not the preferred way of solving this problem. We offered suggestions on how to accomplish your goals in a way that would be acceptable upstream and I would encourage you to investigate those options further. -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [TOMOYO 15/15] LSM expansion for TOMOYO Linux.
On Monday 03 September 2007 9:15:27 am Tetsuo Handa wrote: > Hello. Hi. > Paul Moore wrote: > > I apologize for not recognizing your approach from our earlier discussion > > on the LSM mailing list in July. Unfortunately, I have the same > > objections to these changes that I did back then and from what I can > > recall of the discussion the rest of the kernel networking community > > agreed that these changes are not the preferred way of solving this > > problem. We offered suggestions on how to accomplish your goals in a way > > that would be acceptable upstream and I would encourage you to > > investigate those options further. > > When I proposed a patch in July, I was patching at post-copy_to_user() step > (i.e. after sock_recvmsg()). > This approach messed up user-supplied buffer. > > This time, I'm patching at pre-copy_to_user() step > (i.e. at skb_recv_datagram()). > This approach doesn't mess up user-supplied buffer. > I think this is a cleaner way than the previous patch. It might be cleaner than your previous patch but it ignores some of the more important points that were brought up by the community in previous discussions. > Although read() gets an error when select() said "read ready", > I can't find other place to use for accomplishing my goals. > > By the way, similar thing can happen when select() against > a file descriptor said "read ready" but read() gets an error > if security policy or security-id of the file has changed > between select() and read(), isn't it? > And such behavior is acceptable, isn't it? > If such behavior can happen and is acceptable and *preferable*, > I think checking permission at dequeue time (i.e. skb_recv_datagram()) > is *preferable* way than checking permission at enqueue time > (i.e. socket_sock_rcv_skb()). As mentioned before that problem with enforcing access control at "dequeue" time is that the system has already accepted the packet from the remote host - how do you plan to deal with these unacceptable/bad packets sitting on a socket, waiting to be read by a process which does not have access to them? What about connection oriented sockets where the remote host will assume everything is okay and continue blasting the machine with more, illegal packets? If you aren't going to allow the socket/application to read the packet, never allow the system to accept it in the first place. The *preferable* solution, as previously stated before by several people, is to investigate other access control methods like the netfilter userspace queue mechanism. At the very least, please explain how the approaches we proposed will not accomplish what you require. -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [TOMOYO 15/15] LSM expansion for TOMOYO Linux.
On Tuesday 04 September 2007 10:02:46 am Tetsuo Handa wrote: > According to Patrick McHardy's posting at > http://www.mail-archive.com/linux-security-module@vger.kernel.org/msg00999. >html netfilter *socket filters* cannot know final recipient process. > Can netfilter *userspace queue mechanism* know final recipient process? Okay, I just went back and re-read the conversation from July as well as the description of your current patches and I think what is basically comes down to is that your design makes use of userspace intervention to allow/reject connections and/or packets based on the application's domain. Unfortunately for TOMOYO, the current LSM network hooks are placed in such a way that you can not block and query a userspace agent for an access control decision. Myself and some others have suggested using the netfilter userspace queue mechanism[1]. However, I understand this may cause you problems when you try to determine the incoming packet's destination/domain. With these requirements I understand why you are pushing so hard to introduce these new LSM hooks, but for many reasons I would really prefer to try and find a way to utilize the existing hooks. I've tried to think of a way to do this over the past day and have not been able to arrive at a clean solution. Personally, I still question the wisdom of receiving a packet/connection only to drop/reject it later when an application tries to read it but I might be the only one. Based on some of the other discussion around this patch there appears to be other, larger issues which you still need to sort out (language parser in the kernel, /proc issues, etc.). I would recommend addressing those concerns and including the netdev mailing list on your next patchset as they might have some thoughts on your network design. [1]http://www.netfilter.org/projects/libnetfilter_queue/index.html -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [TOMOYO 15/15] LSM expansion for TOMOYO Linux.
On Thursday, September 6 2007 9:04:01 am Tetsuo Handa wrote: > (1) It uses userspace intervention to allow/reject > connections and/or packets based on the application's domain. > Since existent hooks can't be used for this purpose, > I inserted a new hook post_recv_datagram() at skb_recv_datagram() > and I modified socket_post_accept() to return error so that > I can drop/disconnect based on the application's domain. > > I think skb_recv_datagram() is the only place that can remove > a message picked up with MSG_PEEK flags from the receive queue. > To remove a message picked up with MSG_PEEK flags, I noticed that > I have to do skb_kill_datagram()-like operation so that > "the head message that must not be delivered to the caller" won't > prevent picking up of "the non-head message that should be delivered to the > caller" when the caller repeats only recv(MSG_PEEK) requests. > Since skb_recv_datagram() can be called from interrupt context, > I have to use spin_lock_irqsave() instead for spin_lock_bh(), am I > right? There are almost certainly better people to answer locking questions, but here is my take on it ... If you are accessing data both in a bottom half and elsewhere you need to make sure you disable bottom halfs from running before you access the data outside the bottom half (spin_lock_bh()). If you are accessing data both in an interrupt handler and elsewhere you need to make sure you disable interrupts when accessing data outside the irq handler (spin_lock_irqsave()). > By the way, why can't socket_post_accept() fail? > Someone may wish to do memory allocation at socket_post_accept(). > socket_accept() is too early for memory allocation because > there is no chance to free allocated memory > when sock->ops->accept() failed. > I think socket_post_accept() should be able to fail. >From my experience the community disapproves of approaches which go through the entire TCP handshake and then terminate the connection, which is what allowing security_socket_post_accept() to fail would do. -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] Version 3 (2.6.23-rc8) Smack: Simplified Mandatory Access Control Kernel
On Sunday 30 September 2007 3:07:42 pm Theodore Tso wrote: > There are different kinds of security. Not all of them involve > cryptography and IPSEC. Some of them involve armed soldiers and air > gap firewalls. :-) > > Yes, normally the network is outside the Trusted Computing Base (TCB), > but a cluster of Linux machines in a rack is roughly the same size of > a huge Unix server tens year ago --- and it's not like Ethernet is any > more secure than the PCI bus. So why do we consider communications > across a PCI bus secure even though they aren't encrypted? Why, > because normally we assume the PCI bus is inside the trust boundary, > and so we don't worry about bad guys tapping communications between > the CPU and the hard drive on the PCI bus. > > But these days, it is obviously possible to create clusters where > certain network interfaces are only connected to machines contained > completely inside the trust boundary, just like a PCI bus in a > traditional server. So don't be so quick to dismiss something like > CIPSO out of hand, just because it doesn't use IPSEC. Sorry I'm a bit late to the discussion (been busy doing "weekend" things), but I see that Casey, Josh, and Ted have already given a pretty good explanation of why CIPSO is not as "evil" as it appears at first glance. I won't restate the points they have already made, but I think there are two other points worth mentioning: The first is that CIPSO options are immutable, which means they work wonderfully with IPsec. Label integrity can be provided through the use of AH and/or tunneled ESP, label confidentiality can be provided through tunneled ESP. While the SELinux specific labeled IPsec implementation we currently have in the kernel is nice if you are talking to other SELinux machines, it has a very real handicap in that you can't use it to talk anything else. CIPSO, or CIPSO in combination with standard, non-labeled IPsec, can be used to talk to pretty much any trusted OSs out there. Adherence to standards and interoperability with other OSs have always been a key factor of Linux's acceptance into new areas; support for CIPSO is just another part of this drive for greater interoperability. The second point I wanted to make is that in the course of putting together the CIPSO implementation in the kernel I ended up talking with a few people who were involved in the original TSIG effort and the mess with the IETF. >From what I could gather, the main technical complaint (other than a variety of political complaints which aren't relevant to our discussion here) was that CIPSO options are difficult to parse (they are, look at the format - it's an option within an option format - yuck) and the intermediate node vendors did not like it all (too much work to do in a fastpath ASIC). After all, look at the [R]IPSO RFC, dated only eight months earlier, and there is no cryptographic "special sauce" in that protocol. CIPSO isn't for everyone, I'll be the first to admit that. However, if you look at the mailing list archive for the Linux LSPP effort, the SELinux list, and to a lesser extent the netdev and LSM lists you will see that there are a set of users who care very much about this functionality. Our support of CIPSO is helping Linux operate in areas it wouldn't be able to elsewhere and I consider that a "win". -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] Version 3 (2.6.23-rc8) Smack: Simplified Mandatory Access Control Kernel
On Sunday 30 September 2007 4:16:18 am Andrew Morton wrote: > - hm, netlabels. Who might be a suitable person to review that code? > Seems that Paul Moore is the man. Maybe he'd be interested in taking a > look over it (please?) Yep, I've been tracking Casey's work on this since the first patch and sending comments when appropriate. I'm going to take a look at the latest rev of the patch and if anything looks awry I'll be sure to let Casey know. The only real wart that still remains from the original patch is the code in smk_cipso_doi() which has a nice comment at the top saying that Paul and Casey need to work out an appropriate interface between NetLabel and SMACK. We punted on it before because SMACK's future was still a bit uncertain and SELinux has no need for an interface like this at present. Now that SMACK looks to be queued up for 2.6.24 it's time to revisit this discussion. -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] Version 4 (2.6.23-rc8-mm2) Smack: Simplified Mandatory Access Control Kernel
On Wednesday 03 October 2007 12:45:42 am Casey Schaufler wrote: > From: Casey Schaufler <[EMAIL PROTECTED]> > > Smack is the Simplified Mandatory Access Control Kernel. > > Smack implements mandatory access control (MAC) using labels > attached to tasks and data containers, including files, SVIPC, > and other tasks. Smack is a kernel based scheme that requires > an absolute minimum of application support and a very small > amount of configuration data. > > {snip} > > This patch includes changes made by Paul Moore <[EMAIL PROTECTED]> > in support of a more comfortable interface to initialize the > CIPSO code from within the kernel. The changes in the net directory > are Pauls, as is the update to netlabel.h My sign-off got lost when Casey smooshed the patch I sent him into the SMACK mega-patch so I'll throw it back in the thread for accounting purposes. Signed-off-by: Paul Moore <[EMAIL PROTECTED]> As for SMACK's use of NetLabel - it looks fine to me, especially now that there is better preservation of the NetLabel/LSM boundary. As has been discussed on the various lists during earlier revisions of the patch I believe there are still some optimizations that can be made regarding how SMACK uses NetLabel but that is something we can always work on at a later date. Acked-by: Paul Moore <[EMAIL PROTECTED]> -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] Version 7 (2.6.23) Smack: Simplified Mandatory Access Control Kernel
On Sunday 14 October 2007 11:30:53 pm Casey Schaufler wrote: > --- "Ahmed S. Darwish" <[EMAIL PROTECTED]> wrote: > > Hi Casey, > > > > On Sun, Oct 14, 2007 at 10:15:42AM -0700, Casey Schaufler wrote: > > > + > > > +CIPSO Configuration > > > + > > > +It is normally unnecessary to specify the CIPSO configuration. The > > > default +values used by the system handle all internal cases. Smack > > > will compose > > > > CIPSO > > > > > +label values to match the Smack labels being used without > > > administrative +intervention. > > > > I have two issues with CIPSO and Smack: > > > > 1- > > > > Using default configuration (system startup script + smacfs fstab line), > > system > > can't access any service outside the Lan. "ICMP parameter problem > > message" always > > appear from the first Wan router (traceroute + tcpdump at [1]). > > > > Services inside the LAN can be accessed normally. System can connect to a > > Lan Windows share. It also connects to the gateway HTTP server easily. > > > > After some tweaking, I discovered that using CIPSOv6 solves all above > > problems: > > $ echo -n "NLBL_CIPSOv6" > /smack/nltype > > > > Is this a normal behaviour ? > > Well ... sort of. CIPSOv6 isn't actually implemented in the > labeled networking code. What you're seeing is unlabeled packets. > > As far as CIPSOv4 and your WAN router, It is possible that it is > configured either to reject CIPSO packets or to allow only CIPSO > packets in a particular DOI or to enforce a CIPSO policy of its > own. The how/why of the packet rejection probably isn't all that important, but the most likely scenario based on the ICMP error code is that the router simply does not know about the CIPSO IP option type and is dropping the packet as a result. I'd be very surprised to see a standard router in general use which has policy to perform packet level access control using CIPSO options/labels. -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v6 00/13] Labeled networking patches
This is an update to the patcheset sent earlier this week and the first time these patches have been sent to the LSM list. The most notable change between this patchset and the "v5" patches is the addition of the fallback/static label patches that were discussed on the SELinux list a few months ago. In addition to just porting the old fallback/static patches I've added the concept of a "default" interface as well as some intelligence in the SELinux layer to allow the NetLabel provided fallback label to play nicely with XFRM labels when both are present on a connection. This should help address issues found in the earlier versions of the fallback/static label patches. This patchset does not include Venkat's flow control patches, but Venkat has promised that they will be ready very soon; when they are I will merge them into this patchset. On a similar note, the new "peer" SELinux object class in this patchset isn't usable with currently released SELinux policies so you'll still be using the separate, labeling protocol specific, access checks. I have to caution against using these patches for anything critical as they are still a "work in progress" and have only received minimal testing. However, I know there are a few of you who are very interested in this functionality and have offered to help with the testing so I'm posting the patches in this early state so we can get a jump shaking the bugs out. For those of you who are playing with these patches, there are a few things worth noting: * You can do a pull down a complete git tree with these changes here: -> git://git.infradead.org/users/pcmoore/lblnet-2.6_testing * You should probably also apply this patch to fix an unrelated panic: -> http://git.kernel.org/?p=linux/kernel/git/jmorris/selinux-2.6.git;a=commitdiff;h=6d2b685564ba417f4c6d80c3661f0dfee13fff85 * You'll need the latest SVN (rev 49 or higher) of the static_label branch of netlabel_tools to make use of the new fallback/static label features: -> http://netlabel.svn.sourceforge.net/viewvc/netlabel/netlabel_tools To configure the new fallback/static labels you use the following netlabelctl commands: * Add a label "netlabelctl unlbl add default|interface: address:[/] \ label:" DEV = interface ADDR = IP address MASK = size of address mask LABEL = full SELinux context Examples: # netlabelctl unlbl add default address:10.0.0.0/8 \ label:system_u:object_r:unlabeled_t:s0 # netlabelctl unlbl add interface:eth0 address:192.168.0.1 \ label:system_u:object_r:unlabeled_t:s0 # netlabelctl unlbl add interface:lo address:::1 \ label:system_u:object_r:unlabeled_t:s0 * Remove a label "netlabelctl unlbl del default|interface: address:[/]" DEV = interface ADDR = IP address MASK = size of address mask Examples: # netlabelctl unlbl del default address:10.0.0.0/8 # netlabelctl unlbl del interface:eth0 address:192.168.0.1 # netlabelctl unlbl del interface:lo address:::1 * Show labels "netlabelctl -p unlbl list" Examples: # netlabelctl unlbl list # netlabelctl -p unlbl list If you have any questions/problems/comments feel free to either drop me mail privately or post something to the list. Thanks. -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v6 01/13] NetLabel: remove unneeded RCU read locks
This patch removes some unneeded RCU read locks as we can treat the reads as "safe" even without RCU. It also converts the NetLabel configuration refcount from a spinlock protected u32 into atomic_t to be more consistent with the rest of the kernel. --- net/netlabel/netlabel_cipso_v4.c |5 ++- net/netlabel/netlabel_kapi.c |3 +- net/netlabel/netlabel_mgmt.c | 63 ++--- net/netlabel/netlabel_mgmt.h |7 ++-- net/netlabel/netlabel_unlabeled.c | 17 ++ 5 files changed, 15 insertions(+), 80 deletions(-) diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index ba0ca8d..becf91a 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "netlabel_user.h" #include "netlabel_cipso_v4.h" @@ -421,7 +422,7 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info) break; } if (ret_val == 0) - netlbl_mgmt_protocount_inc(); + atomic_inc(&netlabel_mgmt_protocount); audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD, &audit_info); @@ -698,7 +699,7 @@ static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info) &audit_info, netlbl_cipsov4_doi_free); if (ret_val == 0) - netlbl_mgmt_protocount_dec(); + atomic_dec(&netlabel_mgmt_protocount); audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_DEL, &audit_info); diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 4f50949..d3762ea 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "netlabel_domainhash.h" #include "netlabel_unlabeled.h" @@ -262,7 +263,7 @@ int netlbl_enabled(void) /* At some point we probably want to expose this mechanism to the user * as well so that admins can toggle NetLabel regardless of the * configuration */ - return (netlbl_mgmt_protocount_value() > 0 ? 1 : 0); + return (atomic_read(&netlabel_mgmt_protocount) > 0); } /** diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index 5648337..e2258dc 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c @@ -37,14 +37,14 @@ #include #include #include +#include #include "netlabel_domainhash.h" #include "netlabel_user.h" #include "netlabel_mgmt.h" -/* NetLabel configured protocol count */ -static DEFINE_SPINLOCK(netlabel_mgmt_protocount_lock); -static u32 netlabel_mgmt_protocount = 0; +/* NetLabel configured protocol counter */ +atomic_t netlabel_mgmt_protocount = ATOMIC_INIT(0); /* Argument struct for netlbl_domhsh_walk() */ struct netlbl_domhsh_walk_arg { @@ -71,63 +71,6 @@ static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = { }; /* - * NetLabel Misc Managment Functions - */ - -/** - * netlbl_mgmt_protocount_inc - Increment the configured labeled protocol count - * - * Description: - * Increment the number of labeled protocol configurations in the current - * NetLabel configuration. Keep track of this for use in determining if - * NetLabel label enforcement should be active/enabled or not in the LSM. - * - */ -void netlbl_mgmt_protocount_inc(void) -{ - spin_lock(&netlabel_mgmt_protocount_lock); - netlabel_mgmt_protocount++; - spin_unlock(&netlabel_mgmt_protocount_lock); -} - -/** - * netlbl_mgmt_protocount_dec - Decrement the configured labeled protocol count - * - * Description: - * Decrement the number of labeled protocol configurations in the current - * NetLabel configuration. Keep track of this for use in determining if - * NetLabel label enforcement should be active/enabled or not in the LSM. - * - */ -void netlbl_mgmt_protocount_dec(void) -{ - spin_lock(&netlabel_mgmt_protocount_lock); - if (netlabel_mgmt_protocount > 0) - netlabel_mgmt_protocount--; - spin_unlock(&netlabel_mgmt_protocount_lock); -} - -/** - * netlbl_mgmt_protocount_value - Return the number of configured protocols - * - * Description: - * Return the number of labeled protocols in the current NetLabel - * configuration. This value is useful in determining if NetLabel label - * enforcement should be active/enabled or not in the LSM. - * - */ -u32 netlbl_mgmt_protocount_value(void) -{ - u32 val; - - rcu_read_lock(); - val = netlabel_mgmt_protocount; - rcu_read_unlock(); - - return val; -} - -/* * NetLabel Command Handlers */ diff --git a/net/netlabel/netlabel_mgmt.h b/net/netlabel/netlabel_mgmt.h index ccb2b39..a43bff1 100644 --- a/net/netlabel/netlabel_mgmt.h +++
[RFC PATCH v6 02/13] NetLabel: cleanup the LSM domain hash functions
The NetLabel/LSM domain hash table search function used a argument to specify if the default entry should be returned if an exact match couldn't be found in the hash table. This is a bit against the kernel's style so make two separate functions to represent the separate behaviors. --- net/netlabel/netlabel_domainhash.c | 47 ++-- 1 files changed, 34 insertions(+), 13 deletions(-) diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index b3675bd..1f8f7ac 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c @@ -109,17 +109,14 @@ static u32 netlbl_domhsh_hash(const char *key) /** * netlbl_domhsh_search - Search for a domain entry * @domain: the domain - * @def: return default if no match is found * * Description: * Searches the domain hash table and returns a pointer to the hash table - * entry if found, otherwise NULL is returned. If @def is non-zero and a - * match is not found in the domain hash table the default mapping is returned - * if it exists. The caller is responsibile for the rcu hash table locks - * (i.e. the caller much call rcu_read_[un]lock()). + * entry if found, otherwise NULL is returned. The caller is responsibile for + * the rcu hash table locks (i.e. the caller much call rcu_read_[un]lock()). * */ -static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain, u32 def) +static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain) { u32 bkt; struct netlbl_dom_map *iter; @@ -133,10 +130,31 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain, u32 def) return iter; } - if (def != 0) { - iter = rcu_dereference(netlbl_domhsh_def); - if (iter != NULL && iter->valid) - return iter; + return NULL; +} + +/** + * netlbl_domhsh_search_def - Search for a domain entry + * @domain: the domain + * @def: return default if no match is found + * + * Description: + * Searches the domain hash table and returns a pointer to the hash table + * entry if an exact match is found, if an exact match is not present in the + * hash table then the default entry is returned if valid otherwise NULL is + * returned. The caller is responsibile for the rcu hash table locks + * (i.e. the caller much call rcu_read_[un]lock()). + * + */ +static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain) +{ + struct netlbl_dom_map *entry; + + entry = netlbl_domhsh_search(domain); + if (entry == NULL) { + entry = rcu_dereference(netlbl_domhsh_def); + if (entry != NULL && entry->valid) + return entry; } return NULL; @@ -224,7 +242,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, if (entry->domain != NULL) { bkt = netlbl_domhsh_hash(entry->domain); spin_lock(&netlbl_domhsh_lock); - if (netlbl_domhsh_search(entry->domain, 0) == NULL) + if (netlbl_domhsh_search(entry->domain) == NULL) list_add_tail_rcu(&entry->list, &rcu_dereference(netlbl_domhsh)->tbl[bkt]); else @@ -307,7 +325,10 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) struct audit_buffer *audit_buf; rcu_read_lock(); - entry = netlbl_domhsh_search(domain, (domain != NULL ? 0 : 1)); + if (domain) + entry = netlbl_domhsh_search(domain); + else + entry = netlbl_domhsh_search_def(domain); if (entry == NULL) goto remove_return; switch (entry->type) { @@ -377,7 +398,7 @@ int netlbl_domhsh_remove_default(struct netlbl_audit *audit_info) */ struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain) { - return netlbl_domhsh_search(domain, 1); + return netlbl_domhsh_search_def(domain); } /** - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v6 05/13] SELinux: add secctx_to_secid() LSM hook
Add a secctx_to_secid() LSM hook to go along with the existing secid_to_secctx() LSM hook. This patch also includes a SELinux implementation for this hook. --- include/linux/security.h | 13 + security/dummy.c |6 ++ security/security.c |6 ++ security/selinux/hooks.c |6 ++ 4 files changed, 31 insertions(+), 0 deletions(-) diff --git a/include/linux/security.h b/include/linux/security.h index ac05083..db19c92 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1183,6 +1183,10 @@ struct request_sock; * Convert secid to security context. * @secid contains the security ID. * @secdata contains the pointer that stores the converted security context. + * @secctx_to_secid: + * Convert security context to secid. + * @secid contains the pointer to the generated security ID. + * @secdata contains the security context. * * @release_secctx: * Release the security context. @@ -1371,6 +1375,7 @@ struct security_operations { int (*getprocattr)(struct task_struct *p, char *name, char **value); int (*setprocattr)(struct task_struct *p, char *name, void *value, size_t size); int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen); + int (*secctx_to_secid)(char *secdata, u32 seclen, u32 *secid); void (*release_secctx)(char *secdata, u32 seclen); #ifdef CONFIG_SECURITY_NETWORK @@ -1603,6 +1608,7 @@ int security_setprocattr(struct task_struct *p, char *name, void *value, size_t int security_netlink_send(struct sock *sk, struct sk_buff *skb); int security_netlink_recv(struct sk_buff *skb, int cap); int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); +int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid); void security_release_secctx(char *secdata, u32 seclen); #else /* CONFIG_SECURITY */ @@ -2280,6 +2286,13 @@ static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *secle return -EOPNOTSUPP; } +static inline int security_secctx_to_secid(char *secdata, + u32 seclen, + u32 *secid) +{ + return -EOPNOTSUPP; +} + static inline void security_release_secctx(char *secdata, u32 seclen) { } diff --git a/security/dummy.c b/security/dummy.c index 6d895ad..767d5a7 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -928,6 +928,11 @@ static int dummy_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) return -EOPNOTSUPP; } +static int dummy_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) +{ + return -EOPNOTSUPP; +} + static void dummy_release_secctx(char *secdata, u32 seclen) { } @@ -1086,6 +1091,7 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, getprocattr); set_to_dummy_if_null(ops, setprocattr); set_to_dummy_if_null(ops, secid_to_secctx); + set_to_dummy_if_null(ops, secctx_to_secid); set_to_dummy_if_null(ops, release_secctx); #ifdef CONFIG_SECURITY_NETWORK set_to_dummy_if_null(ops, unix_stream_connect); diff --git a/security/security.c b/security/security.c index 0e1f1f1..3bdcada 100644 --- a/security/security.c +++ b/security/security.c @@ -816,6 +816,12 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) } EXPORT_SYMBOL(security_secid_to_secctx); +int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) +{ + return security_ops->secctx_to_secid(secdata, seclen, secid); +} +EXPORT_SYMBOL(security_secctx_to_secid); + void security_release_secctx(char *secdata, u32 seclen) { return security_ops->release_secctx(secdata, seclen); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 9f3124b..8bb673b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4710,6 +4710,11 @@ static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) return security_sid_to_context(secid, secdata, seclen); } +static int selinux_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) +{ + return security_context_to_sid(secdata, seclen, secid); +} + static void selinux_release_secctx(char *secdata, u32 seclen) { kfree(secdata); @@ -4898,6 +4903,7 @@ static struct security_operations selinux_ops = { .setprocattr = selinux_setprocattr, .secid_to_secctx = selinux_secid_to_secctx, + .secctx_to_secid = selinux_secctx_to_secid, .release_secctx = selinux_release_secctx, .unix_stream_connect = selinux_socket_unix_stream_connect, - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v6 07/13] SELinux: Add a capabilities bitmap to SELinux policy version 22
Add a new policy capabilities bitmap to SELinux policy version 22. This bitmap will enable the security server to query the policy to determine which features it supports. --- security/selinux/Kconfig|2 - security/selinux/include/security.h | 15 ++ security/selinux/selinuxfs.c| 89 +-- security/selinux/ss/policydb.c | 18 +++ security/selinux/ss/policydb.h |2 + security/selinux/ss/services.c | 67 ++ 6 files changed, 185 insertions(+), 8 deletions(-) diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index b32a459..2b517d6 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig @@ -145,7 +145,7 @@ config SECURITY_SELINUX_POLICYDB_VERSION_MAX config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE int "NSA SELinux maximum supported policy format version value" depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX - range 15 21 + range 15 22 default 19 help This option sets the value for the maximum policy format version diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 39337af..4d3c0d3 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -25,13 +25,14 @@ #define POLICYDB_VERSION_MLS 19 #define POLICYDB_VERSION_AVTAB 20 #define POLICYDB_VERSION_RANGETRANS21 +#define POLICYDB_VERSION_POLCAP22 /* Range of policy versions we understand*/ #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE #else -#define POLICYDB_VERSION_MAX POLICYDB_VERSION_RANGETRANS +#define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP #endif struct netlbl_lsm_secattr; @@ -39,8 +40,19 @@ struct netlbl_lsm_secattr; extern int selinux_enabled; extern int selinux_mls_enabled; +/* Policy capabilities */ +enum { + POLICYDB_CAPABILITY_NETPEER, + __POLICYDB_CAPABILITY_MAX +}; +#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1) + +extern int selinux_policycap_netpeer; + int security_load_policy(void * data, size_t len); +int security_policycap_supported(unsigned int req_cap); + #define SEL_VEC_MAX 32 struct av_decision { u32 allowed; @@ -92,6 +104,7 @@ int security_get_classes(char ***classes, int *nclasses); int security_get_permissions(char *class, char ***perms, int *nperms); int security_get_reject_unknown(void); int security_get_allow_unknown(void); +int security_get_policycaps(int *len, int **values); #define SECURITY_FS_USE_XATTR 1 /* use xattr */ #define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */ diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index f5f3e6d..cf583cc 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -2,6 +2,11 @@ * * Added conditional policy language extensions * + * Updated: Hewlett-Packard <[EMAIL PROTECTED]> + * + * Added support for the policy capability bitmap + * + * Copyright (C) 2007 Hewlett-Packard Development Company, L.P. * Copyright (C) 2003 - 2004 Tresys Technology, LLC * Copyright (C) 2004 Red Hat, Inc., James Morris <[EMAIL PROTECTED]> * This program is free software; you can redistribute it and/or modify @@ -35,6 +40,11 @@ #include "objsec.h" #include "conditional.h" +/* Policy capability filenames */ +static char *policycap_names[] = { + "network_peer_controls" +}; + unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; #ifdef CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT @@ -71,6 +81,9 @@ static int *bool_pending_values = NULL; static struct dentry *class_dir = NULL; static unsigned long last_class_ino; +/* global data for policy capabilities */ +static struct dentry *policycap_dir = NULL; + extern void selnl_notify_setenforce(int val); /* Check whether a task is allowed to use a security operation. */ @@ -110,10 +123,11 @@ enum sel_inos { static unsigned long sel_last_ino = SEL_INO_NEXT - 1; -#define SEL_INITCON_INO_OFFSET 0x0100 -#define SEL_BOOL_INO_OFFSET0x0200 -#define SEL_CLASS_INO_OFFSET 0x0400 -#define SEL_INO_MASK 0x00ff +#define SEL_INITCON_INO_OFFSET 0x0100 +#define SEL_BOOL_INO_OFFSET0x0200 +#define SEL_CLASS_INO_OFFSET 0x0400 +#define SEL_POLICYCAP_INO_OFFSET 0x0800 +#define SEL_INO_MASK 0x00ff #define TMPBUFLEN 12 static ssize_t sel_read_enforce(struct file *filp, char __user *buf, @@ -262,6 +276,7 @@ static const struct file_operations sel_policyvers_ops = { /* declaration for sel_write_load */ static int sel_make_bools(void); static int sel_make_classes(void); +static int sel_make_po
[RFC PATCH v6 08/13] SELinux: Add new peer permissions to the Flask definitions
Add additional Flask definitions to support the new "peer" object class. --- security/selinux/include/av_perm_to_string.h |3 +++ security/selinux/include/av_permissions.h|3 +++ security/selinux/include/class_to_string.h |7 +++ security/selinux/include/flask.h |1 + 4 files changed, 14 insertions(+), 0 deletions(-) diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h index 049bf69..1d56a6a 100644 --- a/security/selinux/include/av_perm_to_string.h +++ b/security/selinux/include/av_perm_to_string.h @@ -159,3 +159,6 @@ S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind") S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect") S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero") + S_(SECCLASS_PEER, PEER__FLOW_IN, "flow_in") + S_(SECCLASS_PEER, PEER__FLOW_OUT, "flow_out") + S_(SECCLASS_PEER, PEER__RECV, "recv") diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h index eda89a2..95d4674 100644 --- a/security/selinux/include/av_permissions.h +++ b/security/selinux/include/av_permissions.h @@ -824,3 +824,6 @@ #define DCCP_SOCKET__NODE_BIND0x0040UL #define DCCP_SOCKET__NAME_CONNECT 0x0080UL #define MEMPROTECT__MMAP_ZERO 0x0001UL +#define PEER__FLOW_IN 0x0001UL +#define PEER__FLOW_OUT0x0002UL +#define PEER__RECV0x0004UL diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h index e77de0e..b1b0d1d 100644 --- a/security/selinux/include/class_to_string.h +++ b/security/selinux/include/class_to_string.h @@ -64,3 +64,10 @@ S_(NULL) S_("dccp_socket") S_("memprotect") +S_(NULL) +S_(NULL) +S_(NULL) +S_(NULL) +S_(NULL) +S_(NULL) +S_("peer") diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h index a9c2b20..09e9dd2 100644 --- a/security/selinux/include/flask.h +++ b/security/selinux/include/flask.h @@ -50,6 +50,7 @@ #define SECCLASS_KEY 58 #define SECCLASS_DCCP_SOCKET 60 #define SECCLASS_MEMPROTECT 61 +#define SECCLASS_PEER68 /* * Security identifier indices for initial entities - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v6 10/13] SELinux: Enable dynamic enable/disable of the network access checks
This patch introduces a mechanism for checking when labeled IPsec or SECMARK are in use by keeping introducing a configuration reference counter for each subsystem. In the case of labeled IPsec, whenever a labeled SA or SPD entry is created the labeled IPsec/XFRM reference count is increased and when the entry is removed it is decreased. In the case of SECMARK, when a SECMARK target is created the reference count is increased and later decreased when the target is removed. These reference counters allow SELinux to quickly determine if either of these subsystems are enabled. NetLabel already has a similar mechanism which provides the netlbl_enabled() function. This patch also renames the selinux_relabel_packet_permission() function to selinux_secmark_relabel_packet_permission() as the original name and description were misleading in that they referenced a single packet label which is not the case. --- include/linux/selinux.h | 45 --- net/netfilter/xt_SECMARK.c | 13 ++- security/selinux/exports.c | 20 - security/selinux/hooks.c| 24 - security/selinux/include/xfrm.h | 17 +++ security/selinux/xfrm.c | 18 ++-- 6 files changed, 123 insertions(+), 14 deletions(-) diff --git a/include/linux/selinux.h b/include/linux/selinux.h index d1b7ca6..691170b 100644 --- a/include/linux/selinux.h +++ b/include/linux/selinux.h @@ -120,16 +120,35 @@ void selinux_get_task_sid(struct task_struct *tsk, u32 *sid); int selinux_string_to_sid(char *str, u32 *sid); /** - * selinux_relabel_packet_permission - check permission to relabel a packet - * @sid: ID value to be applied to network packet (via SECMARK, most likely) + * selinux_secmark_relabel_packet_permission - secmark permission check + * @sid: SECMARK ID value to be applied to network packet * - * Returns 0 if the current task is allowed to label packets with the - * supplied security ID. Note that it is implicit that the packet is always - * being relabeled from the default unlabled value, and that the access - * control decision is made in the AVC. + * Returns 0 if the current task is allowed to set the SECMARK label of + * packets with the supplied security ID. Note that it is implicit that + * the packet is always being relabeled from the default unlabeled value, + * and that the access control decision is made in the AVC. */ -int selinux_relabel_packet_permission(u32 sid); +int selinux_secmark_relabel_packet_permission(u32 sid); +/** + * selinux_secmark_refcount_inc - increments the secmark use counter + * + * SELinux keeps track of the current SECMARK targets in use so it knows + * when to apply SECMARK label access checks to network packets. This + * function incements this reference count to indicate that a new SECMARK + * target has been configured. + */ +void selinux_secmark_refcount_inc(void); + +/** + * selinux_secmark_refcount_dec - decrements the secmark use counter + * + * SELinux keeps track of the current SECMARK targets in use so it knows + * when to apply SECMARK label access checks to network packets. This + * function decements this reference count to indicate that one of the + * existing SECMARK targets has been removed/flushed. + */ +void selinux_secmark_refcount_dec(void); #else static inline int selinux_audit_rule_init(u32 field, u32 op, @@ -184,11 +203,21 @@ static inline int selinux_string_to_sid(const char *str, u32 *sid) return 0; } -static inline int selinux_relabel_packet_permission(u32 sid) +static inline int selinux_secmark_relabel_packet_permission(u32 sid) { return 0; } +static inline void selinux_secmark_refcount_inc(void) +{ + return; +} + +static inline void selinux_secmark_refcount_dec(void) +{ + return; +} + #endif /* CONFIG_SECURITY_SELINUX */ #endif /* _LINUX_SELINUX_H */ diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c index 235806e..db4a1fe 100644 --- a/net/netfilter/xt_SECMARK.c +++ b/net/netfilter/xt_SECMARK.c @@ -72,12 +72,13 @@ static bool checkentry_selinux(struct xt_secmark_target_info *info) return false; } - err = selinux_relabel_packet_permission(sel->selsid); + err = selinux_secmark_relabel_packet_permission(sel->selsid); if (err) { printk(KERN_INFO PFX "unable to obtain relabeling permission\n"); return false; } + selinux_secmark_refcount_inc(); return true; } @@ -109,11 +110,20 @@ static bool checkentry(const char *tablename, const void *entry, return true; } +void destroy(const struct xt_target *target, void *targinfo) +{ + switch (mode) { + case SECMARK_MODE_SEL: + selinux_secmark_refcount_dec(); + } +} + static struct xt_target xt_secmark_targ
[RFC PATCH v6 12/13] NetLabel: introduce static network labels for unlabeled connections
Most trusted OSs, with the exception of Linux, have the ability to specify static security labels for unlabeled networks. This patch adds this ability to the NetLabel packet labeling framework. If the NetLabel subsystem is called to determine the security attributes of an incoming packet it first checks to see if any recognized NetLabel packet labeling protocols are in-use on the packet. If none can be found then the unlabled connection table is queried and based on the packets incoming interface and address it is matched with a security label as configured by the administrator using the netlabel_tools package. The matching security label is returned to the caller just as if the packet was explicitly labeled using a labeling protocol. --- include/net/netlabel.h|6 net/netlabel/netlabel_kapi.c | 16 net/netlabel/netlabel_unlabeled.c | 1373 + net/netlabel/netlabel_unlabeled.h | 145 4 files changed, 1522 insertions(+), 18 deletions(-) diff --git a/include/net/netlabel.h b/include/net/netlabel.h index a3bffb4..b3213c7 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -67,7 +67,11 @@ * NetLabel NETLINK protocol */ -#define NETLBL_PROTO_VERSION1 +/* NetLabel NETLINK protocol version + * 1: initial version + * 2: added static labels for unlabeled connections + */ +#define NETLBL_PROTO_VERSION2 /* NetLabel NETLINK types/families */ #define NETLBL_NLTYPE_NONE 0 diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 4914615..c69e3e1 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -312,7 +312,7 @@ socket_setattr_return: * @secattr: the security attributes * * Description: - * Examines the given sock to see any NetLabel style labeling has been + * Examines the given sock to see if any NetLabel style labeling has been * applied to the sock, if so it parses the socket label and returns the * security attributes in @secattr. Returns zero on success, negative values * on failure. @@ -320,13 +320,7 @@ socket_setattr_return: */ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) { - int ret_val; - - ret_val = cipso_v4_sock_getattr(sk, secattr); - if (ret_val == 0) - return 0; - - return netlbl_unlabel_getattr(secattr); + return cipso_v4_sock_getattr(sk, secattr); } /** @@ -350,7 +344,7 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb, cipso_v4_skbuff_getattr(skb, secattr) == 0) return 0; - return netlbl_unlabel_getattr(secattr); + return netlbl_unlabel_getattr(skb, family, secattr); } /** @@ -434,6 +428,10 @@ static int __init netlbl_init(void) if (ret_val != 0) goto init_failure; + ret_val = netlbl_unlabel_init(NETLBL_UNLHSH_BITSIZE); + if (ret_val != 0) + goto init_failure; + ret_val = netlbl_netlink_init(); if (ret_val != 0) goto init_failure; diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 5e11394..add0988 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -10,7 +10,7 @@ */ /* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 + * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - 2007 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,22 +36,88 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include #include #include - +#include +#include #include #include +#include #include "netlabel_user.h" #include "netlabel_domainhash.h" #include "netlabel_unlabeled.h" +#include "netlabel_mgmt.h" + +/* The unlabeled connection hash table which we use to map network interfaces + * and addresses of unlabeled packets to a user specified secid value for the + * LSM. The hash table is used to lookup the network interface entry + * (struct netlbl_unlhsh_iface) and then the interface entry is used to + * lookup an IP address match from an ordered list. If a network interface + * match can not be found in the hash table then the default entry + * (netlbl_unlhsh_def) is used. The IP address entry list + * (struct netlbl_unlhsh_addr) is ordered such that the entries with a + * larger netmask come first. + */ +struct netlbl_unlhsh_tbl { + struct list_head *tbl; + u32 size; +}; +struct netlbl_unlhsh_addr4 { + __be32 addr; + __be32 mask; + u32 secid; + + u32 valid; + struct list_head list; + struct rcu_head rcu; +}; +struct netlbl_unlhsh_addr6 { + struct in6_addr addr; + struct in6_addr mask; + u32 secid; + + u32 valid; + struct list_head list; +
[RFC PATCH v6 13/13] NetLabel: add auditing to the static labeling mechanism
This patch adds auditing support to the NetLabel static labeling mechanism. --- include/linux/audit.h |2 + net/netlabel/netlabel_unlabeled.c | 127 +++-- 2 files changed, 107 insertions(+), 22 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index c687816..bdd6f5d 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -115,6 +115,8 @@ #define AUDIT_MAC_IPSEC_ADDSPD 1413/* Not used */ #define AUDIT_MAC_IPSEC_DELSPD 1414/* Not used */ #define AUDIT_MAC_IPSEC_EVENT 1415/* Audit an IPSec event */ +#define AUDIT_MAC_UNLBL_STCADD 1416/* NetLabel: add a static label */ +#define AUDIT_MAC_UNLBL_STCDEL 1417/* NetLabel: del a static label */ #define AUDIT_FIRST_KERN_ANOM_MSG 1700 #define AUDIT_LAST_KERN_ANOM_MSG1799 diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index add0988..30ebb14 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -519,6 +519,7 @@ add_iface_failure: * @mask: address mask in network byte order * @addr_len: length of address/mask (4 for IPv4, 16 for IPv6) * @secid: LSM secid value for the entry + * @audit_info: NetLabel audit information * * Description: * Adds a new entry to the unlabeled connection hash table. Returns zero on @@ -530,12 +531,18 @@ static int netlbl_unlhsh_add(struct net *net, const void *addr, const void *mask, u32 addr_len, -u32 secid) +u32 secid, +struct netlbl_audit *audit_info) { int ret_val; int ifindex; struct net_device *dev; struct netlbl_unlhsh_iface *iface; + struct in_addr *addr4, *mask4; + struct in6_addr *addr6, *mask6; + struct audit_buffer *audit_buf = NULL; + char *secctx = NULL; + u32 secctx_len; if (addr_len != sizeof(struct in_addr) && addr_len != sizeof(struct in6_addr)) @@ -562,19 +569,25 @@ static int netlbl_unlhsh_add(struct net *net, goto unlhsh_add_return; } } + audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCADD, + audit_info); switch (addr_len) { case sizeof(struct in_addr): - ret_val = netlbl_unlhsh_add_addr4(iface, - (struct in_addr *)addr, - (struct in_addr *)mask, - secid); + addr4 = (struct in_addr *)addr; + mask4 = (struct in_addr *)mask; + ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, secid); + if (audit_buf != NULL) + audit_log_format(audit_buf, " daddr=" NIPQUAD_FMT, +NIPQUAD(addr4->s_addr)); break; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case sizeof(struct in6_addr): - ret_val = netlbl_unlhsh_add_addr6(iface, - (struct in6_addr *)addr, - (struct in6_addr *)mask, - secid); + addr6 = (struct in6_addr *)addr; + mask6 = (struct in6_addr *)mask; + ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid); + if (audit_buf != NULL) + audit_log_format(audit_buf, " daddr= " NIP6_FMT, +NIP6(*addr6)); break; #endif /* IPv6 */ default: @@ -585,6 +598,16 @@ static int netlbl_unlhsh_add(struct net *net, unlhsh_add_return: rcu_read_unlock(); + if (audit_buf != NULL) { + if (security_secid_to_secctx(secid, +&secctx, +&secctx_len) == 0) { + audit_log_format(audit_buf, " sec_obj=%s", secctx); + security_release_secctx(secctx, secctx_len); + } + audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0); + audit_log_end(audit_buf); + } return ret_val; } @@ -593,6 +616,7 @@ unlhsh_add_return: * @iface: interface entry * @addr: IP address * @mask: IP address mask + * @audit_info: NetLabel audit information * * Description: * Remove an IP address entry from the unlabeled connection hash table. @@ -602,10 +626,14 @@ unlhsh_add_return: */ static int netlbl_unlhsh_remove_addr4(struct netlbl_unlhsh_iface *iface, const struct in_addr *addr, - const struct in_addr *m
[RFC PATCH v6 04/13] NetLabel: Add secid token support to the NetLabel secattr struct
This patch adds support to the NetLabel LSM secattr struct for a secid token and a type field, paving the way for full LSM/SELinux context support and "static" or "fallback" labels. In addition, this patch adds a fair amount of documentation to the core NetLabel structures used as part of the NetLabel kernel API. --- include/net/netlabel.h| 91 ++--- net/ipv4/cipso_ipv4.c | 59 +++- net/netlabel/netlabel_unlabeled.c |1 security/selinux/ss/mls.c | 10 ++-- security/selinux/ss/services.c|5 ++ 5 files changed, 120 insertions(+), 46 deletions(-) diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 2e5b2f6..18b73cf 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -105,17 +105,49 @@ struct netlbl_dom_map; /* Domain mapping operations */ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info); -/* LSM security attributes */ +/* + * LSM security attributes + */ + +/** + * struct netlbl_lsm_cache - NetLabel LSM security attribute cache + * @refcount: atomic reference counter + * @free: LSM supplied function to free the cache data + * @data: LSM supplied cache data + * + * Description: + * This structure is provided for LSMs which wish to make use of the NetLabel + * caching mechanism to store LSM specific data/attributes in the NetLabel + * cache. If the LSM has to perform a lot of translation from the NetLabel + * security attributes into it's own internal representation then the cache + * mechanism can provide a way to eliminate some or all of that translation + * overhead on a cache hit. + * + */ struct netlbl_lsm_cache { atomic_t refcount; void (*free) (const void *data); void *data; }; -/* The catmap bitmap field MUST be a power of two in length and large + +/** + * struct netlbl_lsm_secattr_catmap - NetLabel LSM secattr category bitmap + * @startbit: the value of the lowest order bit in the bitmap + * @bitmap: the category bitmap + * @next: pointer to the next bitmap "node" or NULL + * + * Description: + * This structure is used to represent category bitmaps. Due to the large + * number of categories supported by most labeling protocols it is not + * practical to transfer a full bitmap internally so NetLabel adopts a sparse + * bitmap structure modeled after SELinux's ebitmap structure. + * The catmap bitmap field MUST be a power of two in length and large * enough to hold at least 240 bits. Special care (i.e. check the code!) * should be used when changing these values as the LSM implementation * probably has functions which rely on the sizes of these types to speed - * processing. */ + * processing. + * + */ #define NETLBL_CATMAP_MAPTYPE u64 #define NETLBL_CATMAP_MAPCNT4 #define NETLBL_CATMAP_MAPSIZE (sizeof(NETLBL_CATMAP_MAPTYPE) * 8) @@ -127,22 +159,48 @@ struct netlbl_lsm_secattr_catmap { NETLBL_CATMAP_MAPTYPE bitmap[NETLBL_CATMAP_MAPCNT]; struct netlbl_lsm_secattr_catmap *next; }; + +/** + * struct netlbl_lsm_secattr - NetLabel LSM security attributes + * @flags: indicate which attributes are contained in this structure + * @type: indicate the NLTYPE of the attributes + * @domain: the NetLabel LSM domain + * @cache: NetLabel LSM specific cache + * @attr.mls: MLS sensitivity label + * @attr.mls.cat: MLS category bitmap + * @attr.mls.lvl: MLS sensitivity level + * @attr.secid: LSM specific secid token + * + * Description: + * This structure is used to pass security attributes between NetLabel and the + * LSM modules. The flags field is used to specify which fields within the + * struct are valid and valid values can be created by bitwise OR'ing the + * NETLBL_SECATTR_* defines. The domain field is typically set by the LSM to + * specify domain specific configuration settings and is not usually used by + * NetLabel itself when returning security attributes to the LSM. + * + */ #define NETLBL_SECATTR_NONE 0x #define NETLBL_SECATTR_DOMAIN 0x0001 #define NETLBL_SECATTR_CACHE0x0002 #define NETLBL_SECATTR_MLS_LVL 0x0004 #define NETLBL_SECATTR_MLS_CAT 0x0008 +#define NETLBL_SECATTR_SECID0x0010 #define NETLBL_SECATTR_CACHEABLE(NETLBL_SECATTR_MLS_LVL | \ -NETLBL_SECATTR_MLS_CAT) +NETLBL_SECATTR_MLS_CAT | \ +NETLBL_SECATTR_SECID) struct netlbl_lsm_secattr { u32 flags; - + u32 type; char *domain; - - u32 mls_lvl; - struct netlbl_lsm_secattr_catmap *mls_cat; - struct netlbl_lsm_cache *cache; + union { + struct { + struct netlbl_lsm_secattr_catmap *cat; + u32 lvl; + } mls; + u32 secid; + } attr; }; /*
[RFC PATCH v6 06/13] NetLabel: add IP address family information to the netlbl_skbuff_getattr() function
In order to do any sort of IP header inspection of incoming packets we need to know which address family, AF_INET/AF_INET6/etc., it belongs to and since the sk_buff structure does not store this information we need to pass along the address family separate from the packet itself. --- include/net/netlabel.h |2 ++ net/netlabel/netlabel_kapi.c|2 ++ security/selinux/hooks.c| 24 ++-- security/selinux/include/netlabel.h |8 +++- security/selinux/netlabel.c | 12 +--- 5 files changed, 38 insertions(+), 10 deletions(-) diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 18b73cf..a3bffb4 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -363,6 +363,7 @@ int netlbl_sock_setattr(struct sock *sk, int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr); int netlbl_skbuff_getattr(const struct sk_buff *skb, + u16 family, struct netlbl_lsm_secattr *secattr); void netlbl_skbuff_err(struct sk_buff *skb, int error); @@ -415,6 +416,7 @@ static inline int netlbl_sock_getattr(struct sock *sk, return -ENOSYS; } static inline int netlbl_skbuff_getattr(const struct sk_buff *skb, + u16 family, struct netlbl_lsm_secattr *secattr) { return -ENOSYS; diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index d3762ea..4914615 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -332,6 +332,7 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) /** * netlbl_skbuff_getattr - Determine the security attributes of a packet * @skb: the packet + * @family: protocol family * @secattr: the security attributes * * Description: @@ -342,6 +343,7 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) * */ int netlbl_skbuff_getattr(const struct sk_buff *skb, + u16 family, struct netlbl_lsm_secattr *secattr) { if (CIPSO_V4_OPTEXIST(skb) && diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8bb673b..2188b9c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3192,6 +3192,7 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, /** * selinux_skb_extlbl_sid - Determine the external label of a packet * @skb: the packet + * @family: protocol family * @sid: the packet's SID * * Description: @@ -3204,13 +3205,16 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, * selinux_netlbl_skbuff_getsid(). * */ -static void selinux_skb_extlbl_sid(struct sk_buff *skb, u32 *sid) +static void selinux_skb_extlbl_sid(struct sk_buff *skb, + u16 family, + u32 *sid) { u32 xfrm_sid; u32 nlbl_sid; selinux_skb_xfrm_sid(skb, &xfrm_sid); if (selinux_netlbl_skbuff_getsid(skb, +family, (xfrm_sid == SECSID_NULL ? SECINITSID_NETMSG : xfrm_sid), &nlbl_sid) != 0) @@ -3703,7 +3707,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) if (err) goto out; - err = selinux_netlbl_sock_rcv_skb(sksec, skb, &ad); + err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad); if (err) goto out; @@ -3760,11 +3764,19 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff * { u32 peer_secid = SECSID_NULL; int err = 0; + u16 family; + + if (sock) + family = sock->sk->sk_family; + else if (skb->sk) + family = skb->sk->sk_family; + else + family = PF_UNSPEC; - if (sock && sock->sk->sk_family == PF_UNIX) + if (sock && family == PF_UNIX) selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); else if (skb) - selinux_skb_extlbl_sid(skb, &peer_secid); + selinux_skb_extlbl_sid(skb, family, &peer_secid); if (peer_secid == SECSID_NULL) err = -EINVAL; @@ -3825,7 +3837,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, u32 newsid; u32 peersid; - selinux_skb_extlbl_sid(skb, &peersid); + selinux_skb_extlbl_sid(skb, sk->sk_family, &peersid); if (peersid == SECSID_NULL) { req->secid = sksec->sid; req->peer_secid = SECSID_NULL; @@ -3863,7 +3875,7 @@ static void selinux_inet_conn_established(struct sock *sk, { struct sk_security_struct *sksec = sk->sk_security;
[RFC PATCH v6 11/13] SELinux: allow NetLabel to directly cache SIDs
Now that the SELinux NetLabel "base SID" is always the netmsg initial SID we can do a big optimization - caching the SID and not just the MLS attributes. This not only saves a lot of per-packet memory allocations and copies but it has a nice side effect of removing a chunk of code. --- security/selinux/hooks.c|6 -- security/selinux/include/netlabel.h |2 - security/selinux/include/security.h |2 - security/selinux/netlabel.c | 55 ++-- security/selinux/ss/services.c | 124 ++- 5 files changed, 55 insertions(+), 134 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 6f4bea4..ac79ff4 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3231,11 +3231,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) u32 nlbl_type; selinux_skb_xfrm_sid(skb, &xfrm_sid); - selinux_netlbl_skbuff_getsid(skb, -family, -SECINITSID_NETMSG, -&nlbl_type, -&nlbl_sid); + selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid); if (security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index c8c05a6..00a2809 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h @@ -48,7 +48,6 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, -u32 base_sid, u32 *type, u32 *sid); @@ -89,7 +88,6 @@ static inline void selinux_netlbl_sk_security_clone( static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, - u32 base_sid, u32 *type, u32 *sid) { diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index fb807c1..4373a7e 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -125,7 +125,6 @@ int security_genfs_sid(const char *fstype, char *name, u16 sclass, #ifdef CONFIG_NETLABEL int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, - u32 base_sid, u32 *sid); int security_netlbl_sid_to_secattr(u32 sid, @@ -133,7 +132,6 @@ int security_netlbl_sid_to_secattr(u32 sid, #else static inline int security_netlbl_secattr_to_sid( struct netlbl_lsm_secattr *secattr, - u32 base_sid, u32 *sid) { return -EIDRM; diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 6c194f9..ba4f3c8 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -36,6 +36,33 @@ #include "security.h" /** + * selinux_netlbl_sidlookup_cached - Cache a SID lookup + * @skb: the packet + * @secattr: the NetLabel security attributes + * @sid: the SID + * + * Description: + * Query the SELinux security server to lookup the correct SID for the given + * security attributes. If the query is successful, cache the result to speed + * up future lookups. Returns zero on success, negative values on failure. + * + */ +static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, + struct netlbl_lsm_secattr *secattr, + u32 *sid) +{ + int rc; + + rc = security_netlbl_secattr_to_sid(secattr, sid); + if (rc == 0 && + (secattr->flags & NETLBL_SECATTR_CACHEABLE) && + (secattr->flags & NETLBL_SECATTR_CACHE)) + netlbl_cache_add(skb, secattr); + + return rc; +} + +/** * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism * @sk: the socket to label * @sid: the SID to use @@ -142,7 +169,6 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel * @skb: the packet * @family: protocol family - * @base_sid: the SELinux SID to use as a context for MLS only attributes * @type: NetLabel labeling protocol type * @sid: the SID * @@ -154,7 +180,6 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, */ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, -u3
[RFC PATCH v6 03/13] NetLabel: consolidate the LSM domain mapping/hashing locks
Currently we use two separate spinlocks to protect both the hash/mapping table and the default entry. This could be considered a bit foolish because it adds complexity without offering any real performance advantage. This patch removes the dedicated default spinlock and protects the default entry with the hash/mapping table spinlock. --- net/netlabel/netlabel_domainhash.c | 30 +- 1 files changed, 9 insertions(+), 21 deletions(-) diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index 1f8f7ac..9a8ea01 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c @@ -54,9 +54,6 @@ struct netlbl_domhsh_tbl { * hash table should be okay */ static DEFINE_SPINLOCK(netlbl_domhsh_lock); static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL; - -/* Default domain mapping */ -static DEFINE_SPINLOCK(netlbl_domhsh_def_lock); static struct netlbl_dom_map *netlbl_domhsh_def = NULL; /* @@ -239,24 +236,22 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, INIT_RCU_HEAD(&entry->rcu); rcu_read_lock(); + spin_lock(&netlbl_domhsh_lock); if (entry->domain != NULL) { bkt = netlbl_domhsh_hash(entry->domain); - spin_lock(&netlbl_domhsh_lock); if (netlbl_domhsh_search(entry->domain) == NULL) list_add_tail_rcu(&entry->list, &rcu_dereference(netlbl_domhsh)->tbl[bkt]); else ret_val = -EEXIST; - spin_unlock(&netlbl_domhsh_lock); } else { INIT_LIST_HEAD(&entry->list); - spin_lock(&netlbl_domhsh_def_lock); if (rcu_dereference(netlbl_domhsh_def) == NULL) rcu_assign_pointer(netlbl_domhsh_def, entry); else ret_val = -EEXIST; - spin_unlock(&netlbl_domhsh_def_lock); } + spin_unlock(&netlbl_domhsh_lock); audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info); if (audit_buf != NULL) { audit_log_format(audit_buf, @@ -337,23 +332,16 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) entry->domain); break; } - if (entry != rcu_dereference(netlbl_domhsh_def)) { - spin_lock(&netlbl_domhsh_lock); - if (entry->valid) { - entry->valid = 0; + spin_lock(&netlbl_domhsh_lock); + if (entry->valid) { + entry->valid = 0; + if (entry != rcu_dereference(netlbl_domhsh_def)) list_del_rcu(&entry->list); - ret_val = 0; - } - spin_unlock(&netlbl_domhsh_lock); - } else { - spin_lock(&netlbl_domhsh_def_lock); - if (entry->valid) { - entry->valid = 0; + else rcu_assign_pointer(netlbl_domhsh_def, NULL); - ret_val = 0; - } - spin_unlock(&netlbl_domhsh_def_lock); + ret_val = 0; } + spin_unlock(&netlbl_domhsh_lock); audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_DEL, audit_info); if (audit_buf != NULL) { - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v6 09/13] SELinux: Better integration between peer labeling subsystems
Rename the existing selinux_skb_extlbl_sid() function to selinux_skb_peerlbl_sid() and modify it's behavior such that it now reconciles multiple peer/external labels and if reconciliation is not possible it returns an error to the caller. --- security/selinux/hooks.c| 94 ++- security/selinux/include/netlabel.h |3 + security/selinux/include/security.h |4 + security/selinux/netlabel.c |3 + security/selinux/ss/services.c | 85 5 files changed, 154 insertions(+), 35 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 2188b9c..4d13a80 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3190,36 +3190,39 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, } /** - * selinux_skb_extlbl_sid - Determine the external label of a packet + * selinux_skb_peerlbl_sid - Determine the peer label of a packet * @skb: the packet * @family: protocol family - * @sid: the packet's SID + * @sid: the packet's peer label SID * * Description: - * Check the various different forms of external packet labeling and determine - * the external SID for the packet. If only one form of external labeling is - * present then it is used, if both labeled IPsec and NetLabel labels are - * present then the SELinux type information is taken from the labeled IPsec - * SA and the MLS sensitivity label information is taken from the NetLabel - * security attributes. This bit of "magic" is done in the call to - * selinux_netlbl_skbuff_getsid(). + * Check the various different forms of network peer labeling and determine + * the peer label/SID for the packet; most of the magic actually occurs in + * the security server function security_net_peersid_cmp(). The function + * returns zero if the value in @sid is valid (although it may be SECSID_NULL) + * or -EACCES if @sid is invalid due to inconsistencies with the different + * peer labels. * */ -static void selinux_skb_extlbl_sid(struct sk_buff *skb, - u16 family, - u32 *sid) +static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) { u32 xfrm_sid; u32 nlbl_sid; + u32 nlbl_type; selinux_skb_xfrm_sid(skb, &xfrm_sid); - if (selinux_netlbl_skbuff_getsid(skb, -family, -(xfrm_sid == SECSID_NULL ? - SECINITSID_NETMSG : xfrm_sid), -&nlbl_sid) != 0) - nlbl_sid = SECSID_NULL; - *sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid); + selinux_netlbl_skbuff_getsid(skb, +family, +SECINITSID_NETMSG, +&nlbl_type, +&nlbl_sid); + + if (security_net_peersid_resolve(nlbl_sid, nlbl_type, +xfrm_sid, +sid) != 0) + return -EACCES; + + return 0; } /* socket security operations */ @@ -3674,17 +3677,32 @@ out: return err; } +static int selinux_sock_recv_peer_compat(struct sk_security_struct *sksec, +struct sk_buff *skb, +u16 family, +struct avc_audit_data ad) +{ + int err; + + err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad); + if (err) + return err; + + return selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad); +} + static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) { - u16 family; + u16 family = sk->sk_family; char *addrp; - int len, err = 0; + int len; + int err; struct avc_audit_data ad; struct sk_security_struct *sksec = sk->sk_security; + int peer_sid; - family = sk->sk_family; if (family != PF_INET && family != PF_INET6) - goto out; + return 0; /* Handle mapped IPv4 packets arriving via IPv6 sockets */ if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) @@ -3693,10 +3711,14 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) AVC_AUDIT_DATA_INIT(&ad, NET); ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]"; ad.u.net.family = family; - err = selinux_parse_skb(skb, &ad, &addrp, &len, 1, NULL); if (err) - goto out; + return err; + + /* Between selinux_compat_net and selinux_policycap_netpeer this is +* starting to get a bit messy - we need to setup a timetable for +* deprecating some of this old/obsolete functiona
Re: [RFC PATCH v6 05/13] SELinux: add secctx_to_secid() LSM hook
On Friday 09 November 2007 5:19:02 pm Casey Schaufler wrote: > --- Paul Moore <[EMAIL PROTECTED]> wrote: > > Add a secctx_to_secid() LSM hook to go along with the existing > > secid_to_secctx() LSM hook. > > I'll bite. Where does this get used? Patch 12/13, functions netlbl_unlabel_staticadd() and netlbl_unlabel_staticadddef(). It is used to convert a user supplied label into a token which is later passed to the LSM; in the SELinux case it is used directly in an avc_has_perm() call. Go ahead and check, I'll wait ... just please don't bring up the whole getpeercon() issue (essentially the example you chose, although you picked the connectionless version) again. Worrying about something that typically happens only once (if at all) per-connection is not something I want to worry about optimizing if it causes the per-packet case to become more tedious. > There. I got the righteous indignation off my chest. I say to > go ahead with adding this to the LSM ... {snip} Sigh. I agree, the whole tokenized label concept is conceptually very annoying and I'll also agree that it can be frustrating for certain implementations. However, the world we live in (the Linux kernel) makes use of these tokenized labels (secid, SID, etc) because it's all the original LSM folks could get in some places. The fact that this works fine with SELinux (actually works better than fine in some cases) is a happy coincidence and probably the reason things haven't changed much. I _really_ don't want to get into the "one true security model" debate, but the fact remains that as long as SELinux is the only LSM implementation in the mainline kernel there is no reason to change this. If/when SMACK (this is really the immediate source of the "righteous indignation" after all, right?) is merged then it will probably make sense to go revisit some of those earlier decisions regarding these tokenized labels. For me personally, right now I'm just concerned about making sure the labeled networking bits work as well as we can make them work; with SELinux that means using a secid/SID to speed up the per-packet access checks. For SMACK, this will probably mean passing the actual string label. You and I have already talked about this so _you_know_ there is a SMACK friendly solution to the fallback/static label functionality; I just can't justify adding code that serves no purpose in the context (haha!) of the current kernel sources. You know all this Casey, so I have no idea where all of these comments are coming from - bad day at work? Somebody run over your dog? Well, go home, have a beer and forget about it for right now. Get SMACK merged, or any other LSM which highlights the same problem, and we can put that "righteous indignation" to good use; right now, it's just plan tiresome. > In Linux 2.7 I propose that we fix these problems. Not today. Un huh ... in the meantime I'm gonna work with what I have :) -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v6 08/13] SELinux: Add new peer permissions to the Flask definitions
On Sunday 11 November 2007 5:31:44 pm James Morris wrote: > On Fri, 9 Nov 2007, Paul Moore wrote: > > Add additional Flask definitions to support the new "peer" object class. > > Should this be dependent on dynamic class/permission support? I think it's okay to _define_ the Flask definitions regardless of what the policy supports as older policies should simply ignore these definitions. > Or, will these checks only be invoked if labled networking is configured? Bingo! Look at patch 7/13, specifically the 'selinux_policycap_netpeer' variable and then at patch 9/13 where the new access checks are made conditional on this variable. The whole mess needs more testing and verification, but "in theory" it shouldn't cause any breakage with older policies ... if someone does notice something broken please scream loudly. -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v6 09/13] SELinux: Better integration between peer labeling subsystems
On Sunday 11 November 2007 5:34:27 pm James Morris wrote: > On Fri, 9 Nov 2007, Paul Moore wrote: > > + /* Between selinux_compat_net and selinux_policycap_netpeer this is > > +* starting to get a bit messy - we need to setup a timetable for > > +* deprecating some of this old/obsolete functionality so we can > > +* reclaim some level of sanity in this function. */ > > I don't think we can do anything which could potentially break userspace > now. Yeah, I've already had one very long day as a result of that, I'm not in any hurry to do that again :) On a serious note, I thought we could remove specific features after a certain period of time, i.e. Documentation/feature-removal-schedule.txt? My thought is that eventually we can at least remove compat_net, or is that too drastic? > So, this one really needs to be right :-) Yeah, this is the one thing that still worries me and one of the main reasons I keep pushing RFC patches so often. Personally, I'm still a little frustrated at how ugly that function looks. I'm debating putting a check near the top to see if any of the "compatibility" flags are set, meaning an older policy, and if it is just handing off control to a compat function which handles all the ugliness. There might be some duplication of code but the sock_rcv_skb() function would be _much_ cleaner and faster in the "current policy" case. Actually, I think I just talked myself into it ... -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v7 05/13] SELinux: add secctx_to_secid() LSM hook
Add a secctx_to_secid() LSM hook to go along with the existing secid_to_secctx() LSM hook. This patch also includes a SELinux implementation for this hook. --- include/linux/security.h | 13 + security/dummy.c |6 ++ security/security.c |6 ++ security/selinux/hooks.c |6 ++ 4 files changed, 31 insertions(+), 0 deletions(-) diff --git a/include/linux/security.h b/include/linux/security.h index ac05083..db19c92 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1183,6 +1183,10 @@ struct request_sock; * Convert secid to security context. * @secid contains the security ID. * @secdata contains the pointer that stores the converted security context. + * @secctx_to_secid: + * Convert security context to secid. + * @secid contains the pointer to the generated security ID. + * @secdata contains the security context. * * @release_secctx: * Release the security context. @@ -1371,6 +1375,7 @@ struct security_operations { int (*getprocattr)(struct task_struct *p, char *name, char **value); int (*setprocattr)(struct task_struct *p, char *name, void *value, size_t size); int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen); + int (*secctx_to_secid)(char *secdata, u32 seclen, u32 *secid); void (*release_secctx)(char *secdata, u32 seclen); #ifdef CONFIG_SECURITY_NETWORK @@ -1603,6 +1608,7 @@ int security_setprocattr(struct task_struct *p, char *name, void *value, size_t int security_netlink_send(struct sock *sk, struct sk_buff *skb); int security_netlink_recv(struct sk_buff *skb, int cap); int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); +int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid); void security_release_secctx(char *secdata, u32 seclen); #else /* CONFIG_SECURITY */ @@ -2280,6 +2286,13 @@ static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *secle return -EOPNOTSUPP; } +static inline int security_secctx_to_secid(char *secdata, + u32 seclen, + u32 *secid) +{ + return -EOPNOTSUPP; +} + static inline void security_release_secctx(char *secdata, u32 seclen) { } diff --git a/security/dummy.c b/security/dummy.c index 6d895ad..767d5a7 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -928,6 +928,11 @@ static int dummy_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) return -EOPNOTSUPP; } +static int dummy_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) +{ + return -EOPNOTSUPP; +} + static void dummy_release_secctx(char *secdata, u32 seclen) { } @@ -1086,6 +1091,7 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, getprocattr); set_to_dummy_if_null(ops, setprocattr); set_to_dummy_if_null(ops, secid_to_secctx); + set_to_dummy_if_null(ops, secctx_to_secid); set_to_dummy_if_null(ops, release_secctx); #ifdef CONFIG_SECURITY_NETWORK set_to_dummy_if_null(ops, unix_stream_connect); diff --git a/security/security.c b/security/security.c index 0e1f1f1..3bdcada 100644 --- a/security/security.c +++ b/security/security.c @@ -816,6 +816,12 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) } EXPORT_SYMBOL(security_secid_to_secctx); +int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) +{ + return security_ops->secctx_to_secid(secdata, seclen, secid); +} +EXPORT_SYMBOL(security_secctx_to_secid); + void security_release_secctx(char *secdata, u32 seclen) { return security_ops->release_secctx(secdata, seclen); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 9f3124b..8bb673b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4710,6 +4710,11 @@ static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) return security_sid_to_context(secid, secdata, seclen); } +static int selinux_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) +{ + return security_context_to_sid(secdata, seclen, secid); +} + static void selinux_release_secctx(char *secdata, u32 seclen) { kfree(secdata); @@ -4898,6 +4903,7 @@ static struct security_operations selinux_ops = { .setprocattr = selinux_setprocattr, .secid_to_secctx = selinux_secid_to_secctx, + .secctx_to_secid = selinux_secctx_to_secid, .release_secctx = selinux_release_secctx, .unix_stream_connect = selinux_socket_unix_stream_connect, - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v7 08/13] SELinux: Add new peer permissions to the Flask definitions
Add additional Flask definitions to support the new "peer" object class. --- security/selinux/include/av_perm_to_string.h |3 +++ security/selinux/include/av_permissions.h|3 +++ security/selinux/include/class_to_string.h |7 +++ security/selinux/include/flask.h |1 + 4 files changed, 14 insertions(+), 0 deletions(-) diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h index 049bf69..1d56a6a 100644 --- a/security/selinux/include/av_perm_to_string.h +++ b/security/selinux/include/av_perm_to_string.h @@ -159,3 +159,6 @@ S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind") S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect") S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero") + S_(SECCLASS_PEER, PEER__FLOW_IN, "flow_in") + S_(SECCLASS_PEER, PEER__FLOW_OUT, "flow_out") + S_(SECCLASS_PEER, PEER__RECV, "recv") diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h index eda89a2..95d4674 100644 --- a/security/selinux/include/av_permissions.h +++ b/security/selinux/include/av_permissions.h @@ -824,3 +824,6 @@ #define DCCP_SOCKET__NODE_BIND0x0040UL #define DCCP_SOCKET__NAME_CONNECT 0x0080UL #define MEMPROTECT__MMAP_ZERO 0x0001UL +#define PEER__FLOW_IN 0x0001UL +#define PEER__FLOW_OUT0x0002UL +#define PEER__RECV0x0004UL diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h index e77de0e..b1b0d1d 100644 --- a/security/selinux/include/class_to_string.h +++ b/security/selinux/include/class_to_string.h @@ -64,3 +64,10 @@ S_(NULL) S_("dccp_socket") S_("memprotect") +S_(NULL) +S_(NULL) +S_(NULL) +S_(NULL) +S_(NULL) +S_(NULL) +S_("peer") diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h index a9c2b20..09e9dd2 100644 --- a/security/selinux/include/flask.h +++ b/security/selinux/include/flask.h @@ -50,6 +50,7 @@ #define SECCLASS_KEY 58 #define SECCLASS_DCCP_SOCKET 60 #define SECCLASS_MEMPROTECT 61 +#define SECCLASS_PEER68 /* * Security identifier indices for initial entities - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v7 03/13] NetLabel: consolidate the LSM domain mapping/hashing locks
Currently we use two separate spinlocks to protect both the hash/mapping table and the default entry. This could be considered a bit foolish because it adds complexity without offering any real performance advantage. This patch removes the dedicated default spinlock and protects the default entry with the hash/mapping table spinlock. --- net/netlabel/netlabel_domainhash.c | 30 +- 1 files changed, 9 insertions(+), 21 deletions(-) diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index 1f8f7ac..9a8ea01 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c @@ -54,9 +54,6 @@ struct netlbl_domhsh_tbl { * hash table should be okay */ static DEFINE_SPINLOCK(netlbl_domhsh_lock); static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL; - -/* Default domain mapping */ -static DEFINE_SPINLOCK(netlbl_domhsh_def_lock); static struct netlbl_dom_map *netlbl_domhsh_def = NULL; /* @@ -239,24 +236,22 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, INIT_RCU_HEAD(&entry->rcu); rcu_read_lock(); + spin_lock(&netlbl_domhsh_lock); if (entry->domain != NULL) { bkt = netlbl_domhsh_hash(entry->domain); - spin_lock(&netlbl_domhsh_lock); if (netlbl_domhsh_search(entry->domain) == NULL) list_add_tail_rcu(&entry->list, &rcu_dereference(netlbl_domhsh)->tbl[bkt]); else ret_val = -EEXIST; - spin_unlock(&netlbl_domhsh_lock); } else { INIT_LIST_HEAD(&entry->list); - spin_lock(&netlbl_domhsh_def_lock); if (rcu_dereference(netlbl_domhsh_def) == NULL) rcu_assign_pointer(netlbl_domhsh_def, entry); else ret_val = -EEXIST; - spin_unlock(&netlbl_domhsh_def_lock); } + spin_unlock(&netlbl_domhsh_lock); audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info); if (audit_buf != NULL) { audit_log_format(audit_buf, @@ -337,23 +332,16 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) entry->domain); break; } - if (entry != rcu_dereference(netlbl_domhsh_def)) { - spin_lock(&netlbl_domhsh_lock); - if (entry->valid) { - entry->valid = 0; + spin_lock(&netlbl_domhsh_lock); + if (entry->valid) { + entry->valid = 0; + if (entry != rcu_dereference(netlbl_domhsh_def)) list_del_rcu(&entry->list); - ret_val = 0; - } - spin_unlock(&netlbl_domhsh_lock); - } else { - spin_lock(&netlbl_domhsh_def_lock); - if (entry->valid) { - entry->valid = 0; + else rcu_assign_pointer(netlbl_domhsh_def, NULL); - ret_val = 0; - } - spin_unlock(&netlbl_domhsh_def_lock); + ret_val = 0; } + spin_unlock(&netlbl_domhsh_lock); audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_DEL, audit_info); if (audit_buf != NULL) { - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v7 00/13] Labeled networking patches for 2.6.25
This is a relatively minor update to the previous, "v6", patchset which the main difference being an attempt at cleaning up all of the compatibility code in the SELinux networking hooks. The patches might look a bit ugly but I believe the resulting code is much cleaner than in "v6" and should be easier to understand/maintain in the long run. I also took the opportunity to update the SELinux compat_net code to make better use of the socket's security struct which allows us to do away with the spinlock in sock_rcv_skb() and cleanup some of that code. I've updated the git tree last night with these bits backed against Linus' latest which includes the ebitmap patch needed with "v6". The git tree can be found here: * git://git.infradead.org/users/pcmoore/lblnet-2.6_testing There have also been a few small bugfixes to the static_label branch of netlabel_tools. For those of you who are playing with this code I recommend you update to r50 to get the latest bits. As usual, if you have any comments/bug-reports/questions let me know. -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v7 01/13] NetLabel: remove unneeded RCU read locks
This patch removes some unneeded RCU read locks as we can treat the reads as "safe" even without RCU. It also converts the NetLabel configuration refcount from a spinlock protected u32 into atomic_t to be more consistent with the rest of the kernel. --- net/netlabel/netlabel_cipso_v4.c |5 ++- net/netlabel/netlabel_kapi.c |3 +- net/netlabel/netlabel_mgmt.c | 63 ++--- net/netlabel/netlabel_mgmt.h |7 ++-- net/netlabel/netlabel_unlabeled.c | 17 ++ 5 files changed, 15 insertions(+), 80 deletions(-) diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index ba0ca8d..becf91a 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "netlabel_user.h" #include "netlabel_cipso_v4.h" @@ -421,7 +422,7 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info) break; } if (ret_val == 0) - netlbl_mgmt_protocount_inc(); + atomic_inc(&netlabel_mgmt_protocount); audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD, &audit_info); @@ -698,7 +699,7 @@ static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info) &audit_info, netlbl_cipsov4_doi_free); if (ret_val == 0) - netlbl_mgmt_protocount_dec(); + atomic_dec(&netlabel_mgmt_protocount); audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_DEL, &audit_info); diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 4f50949..d3762ea 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "netlabel_domainhash.h" #include "netlabel_unlabeled.h" @@ -262,7 +263,7 @@ int netlbl_enabled(void) /* At some point we probably want to expose this mechanism to the user * as well so that admins can toggle NetLabel regardless of the * configuration */ - return (netlbl_mgmt_protocount_value() > 0 ? 1 : 0); + return (atomic_read(&netlabel_mgmt_protocount) > 0); } /** diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index 5648337..e2258dc 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c @@ -37,14 +37,14 @@ #include #include #include +#include #include "netlabel_domainhash.h" #include "netlabel_user.h" #include "netlabel_mgmt.h" -/* NetLabel configured protocol count */ -static DEFINE_SPINLOCK(netlabel_mgmt_protocount_lock); -static u32 netlabel_mgmt_protocount = 0; +/* NetLabel configured protocol counter */ +atomic_t netlabel_mgmt_protocount = ATOMIC_INIT(0); /* Argument struct for netlbl_domhsh_walk() */ struct netlbl_domhsh_walk_arg { @@ -71,63 +71,6 @@ static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = { }; /* - * NetLabel Misc Managment Functions - */ - -/** - * netlbl_mgmt_protocount_inc - Increment the configured labeled protocol count - * - * Description: - * Increment the number of labeled protocol configurations in the current - * NetLabel configuration. Keep track of this for use in determining if - * NetLabel label enforcement should be active/enabled or not in the LSM. - * - */ -void netlbl_mgmt_protocount_inc(void) -{ - spin_lock(&netlabel_mgmt_protocount_lock); - netlabel_mgmt_protocount++; - spin_unlock(&netlabel_mgmt_protocount_lock); -} - -/** - * netlbl_mgmt_protocount_dec - Decrement the configured labeled protocol count - * - * Description: - * Decrement the number of labeled protocol configurations in the current - * NetLabel configuration. Keep track of this for use in determining if - * NetLabel label enforcement should be active/enabled or not in the LSM. - * - */ -void netlbl_mgmt_protocount_dec(void) -{ - spin_lock(&netlabel_mgmt_protocount_lock); - if (netlabel_mgmt_protocount > 0) - netlabel_mgmt_protocount--; - spin_unlock(&netlabel_mgmt_protocount_lock); -} - -/** - * netlbl_mgmt_protocount_value - Return the number of configured protocols - * - * Description: - * Return the number of labeled protocols in the current NetLabel - * configuration. This value is useful in determining if NetLabel label - * enforcement should be active/enabled or not in the LSM. - * - */ -u32 netlbl_mgmt_protocount_value(void) -{ - u32 val; - - rcu_read_lock(); - val = netlabel_mgmt_protocount; - rcu_read_unlock(); - - return val; -} - -/* * NetLabel Command Handlers */ diff --git a/net/netlabel/netlabel_mgmt.h b/net/netlabel/netlabel_mgmt.h index ccb2b39..a43bff1 100644 --- a/net/netlabel/netlabel_mgmt.h +++
[RFC PATCH v7 02/13] NetLabel: cleanup the LSM domain hash functions
The NetLabel/LSM domain hash table search function used a argument to specify if the default entry should be returned if an exact match couldn't be found in the hash table. This is a bit against the kernel's style so make two separate functions to represent the separate behaviors. --- net/netlabel/netlabel_domainhash.c | 47 ++-- 1 files changed, 34 insertions(+), 13 deletions(-) diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index b3675bd..1f8f7ac 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c @@ -109,17 +109,14 @@ static u32 netlbl_domhsh_hash(const char *key) /** * netlbl_domhsh_search - Search for a domain entry * @domain: the domain - * @def: return default if no match is found * * Description: * Searches the domain hash table and returns a pointer to the hash table - * entry if found, otherwise NULL is returned. If @def is non-zero and a - * match is not found in the domain hash table the default mapping is returned - * if it exists. The caller is responsibile for the rcu hash table locks - * (i.e. the caller much call rcu_read_[un]lock()). + * entry if found, otherwise NULL is returned. The caller is responsibile for + * the rcu hash table locks (i.e. the caller much call rcu_read_[un]lock()). * */ -static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain, u32 def) +static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain) { u32 bkt; struct netlbl_dom_map *iter; @@ -133,10 +130,31 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain, u32 def) return iter; } - if (def != 0) { - iter = rcu_dereference(netlbl_domhsh_def); - if (iter != NULL && iter->valid) - return iter; + return NULL; +} + +/** + * netlbl_domhsh_search_def - Search for a domain entry + * @domain: the domain + * @def: return default if no match is found + * + * Description: + * Searches the domain hash table and returns a pointer to the hash table + * entry if an exact match is found, if an exact match is not present in the + * hash table then the default entry is returned if valid otherwise NULL is + * returned. The caller is responsibile for the rcu hash table locks + * (i.e. the caller much call rcu_read_[un]lock()). + * + */ +static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain) +{ + struct netlbl_dom_map *entry; + + entry = netlbl_domhsh_search(domain); + if (entry == NULL) { + entry = rcu_dereference(netlbl_domhsh_def); + if (entry != NULL && entry->valid) + return entry; } return NULL; @@ -224,7 +242,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, if (entry->domain != NULL) { bkt = netlbl_domhsh_hash(entry->domain); spin_lock(&netlbl_domhsh_lock); - if (netlbl_domhsh_search(entry->domain, 0) == NULL) + if (netlbl_domhsh_search(entry->domain) == NULL) list_add_tail_rcu(&entry->list, &rcu_dereference(netlbl_domhsh)->tbl[bkt]); else @@ -307,7 +325,10 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) struct audit_buffer *audit_buf; rcu_read_lock(); - entry = netlbl_domhsh_search(domain, (domain != NULL ? 0 : 1)); + if (domain) + entry = netlbl_domhsh_search(domain); + else + entry = netlbl_domhsh_search_def(domain); if (entry == NULL) goto remove_return; switch (entry->type) { @@ -377,7 +398,7 @@ int netlbl_domhsh_remove_default(struct netlbl_audit *audit_info) */ struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain) { - return netlbl_domhsh_search(domain, 1); + return netlbl_domhsh_search_def(domain); } /** - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v7 04/13] NetLabel: Add secid token support to the NetLabel secattr struct
This patch adds support to the NetLabel LSM secattr struct for a secid token and a type field, paving the way for full LSM/SELinux context support and "static" or "fallback" labels. In addition, this patch adds a fair amount of documentation to the core NetLabel structures used as part of the NetLabel kernel API. --- include/net/netlabel.h| 91 ++--- net/ipv4/cipso_ipv4.c | 59 +++- net/netlabel/netlabel_unlabeled.c |1 security/selinux/ss/mls.c | 10 ++-- security/selinux/ss/services.c|5 ++ 5 files changed, 120 insertions(+), 46 deletions(-) diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 2e5b2f6..18b73cf 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -105,17 +105,49 @@ struct netlbl_dom_map; /* Domain mapping operations */ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info); -/* LSM security attributes */ +/* + * LSM security attributes + */ + +/** + * struct netlbl_lsm_cache - NetLabel LSM security attribute cache + * @refcount: atomic reference counter + * @free: LSM supplied function to free the cache data + * @data: LSM supplied cache data + * + * Description: + * This structure is provided for LSMs which wish to make use of the NetLabel + * caching mechanism to store LSM specific data/attributes in the NetLabel + * cache. If the LSM has to perform a lot of translation from the NetLabel + * security attributes into it's own internal representation then the cache + * mechanism can provide a way to eliminate some or all of that translation + * overhead on a cache hit. + * + */ struct netlbl_lsm_cache { atomic_t refcount; void (*free) (const void *data); void *data; }; -/* The catmap bitmap field MUST be a power of two in length and large + +/** + * struct netlbl_lsm_secattr_catmap - NetLabel LSM secattr category bitmap + * @startbit: the value of the lowest order bit in the bitmap + * @bitmap: the category bitmap + * @next: pointer to the next bitmap "node" or NULL + * + * Description: + * This structure is used to represent category bitmaps. Due to the large + * number of categories supported by most labeling protocols it is not + * practical to transfer a full bitmap internally so NetLabel adopts a sparse + * bitmap structure modeled after SELinux's ebitmap structure. + * The catmap bitmap field MUST be a power of two in length and large * enough to hold at least 240 bits. Special care (i.e. check the code!) * should be used when changing these values as the LSM implementation * probably has functions which rely on the sizes of these types to speed - * processing. */ + * processing. + * + */ #define NETLBL_CATMAP_MAPTYPE u64 #define NETLBL_CATMAP_MAPCNT4 #define NETLBL_CATMAP_MAPSIZE (sizeof(NETLBL_CATMAP_MAPTYPE) * 8) @@ -127,22 +159,48 @@ struct netlbl_lsm_secattr_catmap { NETLBL_CATMAP_MAPTYPE bitmap[NETLBL_CATMAP_MAPCNT]; struct netlbl_lsm_secattr_catmap *next; }; + +/** + * struct netlbl_lsm_secattr - NetLabel LSM security attributes + * @flags: indicate which attributes are contained in this structure + * @type: indicate the NLTYPE of the attributes + * @domain: the NetLabel LSM domain + * @cache: NetLabel LSM specific cache + * @attr.mls: MLS sensitivity label + * @attr.mls.cat: MLS category bitmap + * @attr.mls.lvl: MLS sensitivity level + * @attr.secid: LSM specific secid token + * + * Description: + * This structure is used to pass security attributes between NetLabel and the + * LSM modules. The flags field is used to specify which fields within the + * struct are valid and valid values can be created by bitwise OR'ing the + * NETLBL_SECATTR_* defines. The domain field is typically set by the LSM to + * specify domain specific configuration settings and is not usually used by + * NetLabel itself when returning security attributes to the LSM. + * + */ #define NETLBL_SECATTR_NONE 0x #define NETLBL_SECATTR_DOMAIN 0x0001 #define NETLBL_SECATTR_CACHE0x0002 #define NETLBL_SECATTR_MLS_LVL 0x0004 #define NETLBL_SECATTR_MLS_CAT 0x0008 +#define NETLBL_SECATTR_SECID0x0010 #define NETLBL_SECATTR_CACHEABLE(NETLBL_SECATTR_MLS_LVL | \ -NETLBL_SECATTR_MLS_CAT) +NETLBL_SECATTR_MLS_CAT | \ +NETLBL_SECATTR_SECID) struct netlbl_lsm_secattr { u32 flags; - + u32 type; char *domain; - - u32 mls_lvl; - struct netlbl_lsm_secattr_catmap *mls_cat; - struct netlbl_lsm_cache *cache; + union { + struct { + struct netlbl_lsm_secattr_catmap *cat; + u32 lvl; + } mls; + u32 secid; + } attr; }; /*
[RFC PATCH v7 10/13] SELinux: Enable dynamic enable/disable of the network access checks
This patch introduces a mechanism for checking when labeled IPsec or SECMARK are in use by keeping introducing a configuration reference counter for each subsystem. In the case of labeled IPsec, whenever a labeled SA or SPD entry is created the labeled IPsec/XFRM reference count is increased and when the entry is removed it is decreased. In the case of SECMARK, when a SECMARK target is created the reference count is increased and later decreased when the target is removed. These reference counters allow SELinux to quickly determine if either of these subsystems are enabled. NetLabel already has a similar mechanism which provides the netlbl_enabled() function. This patch also renames the selinux_relabel_packet_permission() function to selinux_secmark_relabel_packet_permission() as the original name and description were misleading in that they referenced a single packet label which is not the case. --- include/linux/selinux.h | 45 --- net/netfilter/xt_SECMARK.c | 13 ++- security/selinux/exports.c | 20 - security/selinux/hooks.c| 45 --- security/selinux/include/xfrm.h | 17 +++ security/selinux/xfrm.c | 18 ++-- 6 files changed, 137 insertions(+), 21 deletions(-) diff --git a/include/linux/selinux.h b/include/linux/selinux.h index d1b7ca6..691170b 100644 --- a/include/linux/selinux.h +++ b/include/linux/selinux.h @@ -120,16 +120,35 @@ void selinux_get_task_sid(struct task_struct *tsk, u32 *sid); int selinux_string_to_sid(char *str, u32 *sid); /** - * selinux_relabel_packet_permission - check permission to relabel a packet - * @sid: ID value to be applied to network packet (via SECMARK, most likely) + * selinux_secmark_relabel_packet_permission - secmark permission check + * @sid: SECMARK ID value to be applied to network packet * - * Returns 0 if the current task is allowed to label packets with the - * supplied security ID. Note that it is implicit that the packet is always - * being relabeled from the default unlabled value, and that the access - * control decision is made in the AVC. + * Returns 0 if the current task is allowed to set the SECMARK label of + * packets with the supplied security ID. Note that it is implicit that + * the packet is always being relabeled from the default unlabeled value, + * and that the access control decision is made in the AVC. */ -int selinux_relabel_packet_permission(u32 sid); +int selinux_secmark_relabel_packet_permission(u32 sid); +/** + * selinux_secmark_refcount_inc - increments the secmark use counter + * + * SELinux keeps track of the current SECMARK targets in use so it knows + * when to apply SECMARK label access checks to network packets. This + * function incements this reference count to indicate that a new SECMARK + * target has been configured. + */ +void selinux_secmark_refcount_inc(void); + +/** + * selinux_secmark_refcount_dec - decrements the secmark use counter + * + * SELinux keeps track of the current SECMARK targets in use so it knows + * when to apply SECMARK label access checks to network packets. This + * function decements this reference count to indicate that one of the + * existing SECMARK targets has been removed/flushed. + */ +void selinux_secmark_refcount_dec(void); #else static inline int selinux_audit_rule_init(u32 field, u32 op, @@ -184,11 +203,21 @@ static inline int selinux_string_to_sid(const char *str, u32 *sid) return 0; } -static inline int selinux_relabel_packet_permission(u32 sid) +static inline int selinux_secmark_relabel_packet_permission(u32 sid) { return 0; } +static inline void selinux_secmark_refcount_inc(void) +{ + return; +} + +static inline void selinux_secmark_refcount_dec(void) +{ + return; +} + #endif /* CONFIG_SECURITY_SELINUX */ #endif /* _LINUX_SELINUX_H */ diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c index 235806e..db4a1fe 100644 --- a/net/netfilter/xt_SECMARK.c +++ b/net/netfilter/xt_SECMARK.c @@ -72,12 +72,13 @@ static bool checkentry_selinux(struct xt_secmark_target_info *info) return false; } - err = selinux_relabel_packet_permission(sel->selsid); + err = selinux_secmark_relabel_packet_permission(sel->selsid); if (err) { printk(KERN_INFO PFX "unable to obtain relabeling permission\n"); return false; } + selinux_secmark_refcount_inc(); return true; } @@ -109,11 +110,20 @@ static bool checkentry(const char *tablename, const void *entry, return true; } +void destroy(const struct xt_target *target, void *targinfo) +{ + switch (mode) { + case SECMARK_MODE_SEL: + selinux_secmark_refcount_dec(); + } +} + static struct xt_targ
[RFC PATCH v7 11/13] SELinux: allow NetLabel to directly cache SIDs
Now that the SELinux NetLabel "base SID" is always the netmsg initial SID we can do a big optimization - caching the SID and not just the MLS attributes. This not only saves a lot of per-packet memory allocations and copies but it has a nice side effect of removing a chunk of code. --- security/selinux/hooks.c|6 -- security/selinux/include/netlabel.h |2 - security/selinux/include/security.h |2 - security/selinux/netlabel.c | 55 ++-- security/selinux/ss/services.c | 124 ++- 5 files changed, 55 insertions(+), 134 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 22789b5..a8928eb 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3231,11 +3231,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) u32 nlbl_type; selinux_skb_xfrm_sid(skb, &xfrm_sid); - selinux_netlbl_skbuff_getsid(skb, -family, -SECINITSID_NETMSG, -&nlbl_type, -&nlbl_sid); + selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid); if (security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index c8c05a6..00a2809 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h @@ -48,7 +48,6 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, -u32 base_sid, u32 *type, u32 *sid); @@ -89,7 +88,6 @@ static inline void selinux_netlbl_sk_security_clone( static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, - u32 base_sid, u32 *type, u32 *sid) { diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index fb807c1..4373a7e 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -125,7 +125,6 @@ int security_genfs_sid(const char *fstype, char *name, u16 sclass, #ifdef CONFIG_NETLABEL int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, - u32 base_sid, u32 *sid); int security_netlbl_sid_to_secattr(u32 sid, @@ -133,7 +132,6 @@ int security_netlbl_sid_to_secattr(u32 sid, #else static inline int security_netlbl_secattr_to_sid( struct netlbl_lsm_secattr *secattr, - u32 base_sid, u32 *sid) { return -EIDRM; diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index af78cb9..e07adf9 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -36,6 +36,33 @@ #include "security.h" /** + * selinux_netlbl_sidlookup_cached - Cache a SID lookup + * @skb: the packet + * @secattr: the NetLabel security attributes + * @sid: the SID + * + * Description: + * Query the SELinux security server to lookup the correct SID for the given + * security attributes. If the query is successful, cache the result to speed + * up future lookups. Returns zero on success, negative values on failure. + * + */ +static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, + struct netlbl_lsm_secattr *secattr, + u32 *sid) +{ + int rc; + + rc = security_netlbl_secattr_to_sid(secattr, sid); + if (rc == 0 && + (secattr->flags & NETLBL_SECATTR_CACHEABLE) && + (secattr->flags & NETLBL_SECATTR_CACHE)) + netlbl_cache_add(skb, secattr); + + return rc; +} + +/** * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism * @sk: the socket to label * @sid: the SID to use @@ -141,7 +168,6 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel * @skb: the packet * @family: protocol family - * @base_sid: the SELinux SID to use as a context for MLS only attributes * @type: NetLabel labeling protocol type * @sid: the SID * @@ -153,7 +179,6 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, */ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, -u3
[RFC PATCH v7 13/13] NetLabel: add auditing to the static labeling mechanism
This patch adds auditing support to the NetLabel static labeling mechanism. --- include/linux/audit.h |2 + net/netlabel/netlabel_unlabeled.c | 127 +++-- 2 files changed, 107 insertions(+), 22 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index c687816..bdd6f5d 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -115,6 +115,8 @@ #define AUDIT_MAC_IPSEC_ADDSPD 1413/* Not used */ #define AUDIT_MAC_IPSEC_DELSPD 1414/* Not used */ #define AUDIT_MAC_IPSEC_EVENT 1415/* Audit an IPSec event */ +#define AUDIT_MAC_UNLBL_STCADD 1416/* NetLabel: add a static label */ +#define AUDIT_MAC_UNLBL_STCDEL 1417/* NetLabel: del a static label */ #define AUDIT_FIRST_KERN_ANOM_MSG 1700 #define AUDIT_LAST_KERN_ANOM_MSG1799 diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index add0988..30ebb14 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -519,6 +519,7 @@ add_iface_failure: * @mask: address mask in network byte order * @addr_len: length of address/mask (4 for IPv4, 16 for IPv6) * @secid: LSM secid value for the entry + * @audit_info: NetLabel audit information * * Description: * Adds a new entry to the unlabeled connection hash table. Returns zero on @@ -530,12 +531,18 @@ static int netlbl_unlhsh_add(struct net *net, const void *addr, const void *mask, u32 addr_len, -u32 secid) +u32 secid, +struct netlbl_audit *audit_info) { int ret_val; int ifindex; struct net_device *dev; struct netlbl_unlhsh_iface *iface; + struct in_addr *addr4, *mask4; + struct in6_addr *addr6, *mask6; + struct audit_buffer *audit_buf = NULL; + char *secctx = NULL; + u32 secctx_len; if (addr_len != sizeof(struct in_addr) && addr_len != sizeof(struct in6_addr)) @@ -562,19 +569,25 @@ static int netlbl_unlhsh_add(struct net *net, goto unlhsh_add_return; } } + audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCADD, + audit_info); switch (addr_len) { case sizeof(struct in_addr): - ret_val = netlbl_unlhsh_add_addr4(iface, - (struct in_addr *)addr, - (struct in_addr *)mask, - secid); + addr4 = (struct in_addr *)addr; + mask4 = (struct in_addr *)mask; + ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, secid); + if (audit_buf != NULL) + audit_log_format(audit_buf, " daddr=" NIPQUAD_FMT, +NIPQUAD(addr4->s_addr)); break; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case sizeof(struct in6_addr): - ret_val = netlbl_unlhsh_add_addr6(iface, - (struct in6_addr *)addr, - (struct in6_addr *)mask, - secid); + addr6 = (struct in6_addr *)addr; + mask6 = (struct in6_addr *)mask; + ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid); + if (audit_buf != NULL) + audit_log_format(audit_buf, " daddr= " NIP6_FMT, +NIP6(*addr6)); break; #endif /* IPv6 */ default: @@ -585,6 +598,16 @@ static int netlbl_unlhsh_add(struct net *net, unlhsh_add_return: rcu_read_unlock(); + if (audit_buf != NULL) { + if (security_secid_to_secctx(secid, +&secctx, +&secctx_len) == 0) { + audit_log_format(audit_buf, " sec_obj=%s", secctx); + security_release_secctx(secctx, secctx_len); + } + audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0); + audit_log_end(audit_buf); + } return ret_val; } @@ -593,6 +616,7 @@ unlhsh_add_return: * @iface: interface entry * @addr: IP address * @mask: IP address mask + * @audit_info: NetLabel audit information * * Description: * Remove an IP address entry from the unlabeled connection hash table. @@ -602,10 +626,14 @@ unlhsh_add_return: */ static int netlbl_unlhsh_remove_addr4(struct netlbl_unlhsh_iface *iface, const struct in_addr *addr, - const struct in_addr *m
[RFC PATCH v7 09/13] SELinux: Better integration between peer labeling subsystems
Rework the handling of network peer labels so that the different peer labeling subsystems work better together. This includes moving both subsystems to a single "peer" object class which involves not only changes to the permission checks but an improved method of consolidating multiple packet peer labels. As part of this work the inbound packet permission check code has been heavily modified to handle both the old and new behavior in as sane a fashion as possible. --- security/selinux/hooks.c| 214 --- security/selinux/include/netlabel.h |3 security/selinux/include/objsec.h |2 security/selinux/include/security.h |4 + security/selinux/netlabel.c | 10 -- security/selinux/ss/services.c | 85 ++ 6 files changed, 218 insertions(+), 100 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 2188b9c..8aeb1c0 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3190,36 +3190,39 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, } /** - * selinux_skb_extlbl_sid - Determine the external label of a packet + * selinux_skb_peerlbl_sid - Determine the peer label of a packet * @skb: the packet * @family: protocol family - * @sid: the packet's SID + * @sid: the packet's peer label SID * * Description: - * Check the various different forms of external packet labeling and determine - * the external SID for the packet. If only one form of external labeling is - * present then it is used, if both labeled IPsec and NetLabel labels are - * present then the SELinux type information is taken from the labeled IPsec - * SA and the MLS sensitivity label information is taken from the NetLabel - * security attributes. This bit of "magic" is done in the call to - * selinux_netlbl_skbuff_getsid(). + * Check the various different forms of network peer labeling and determine + * the peer label/SID for the packet; most of the magic actually occurs in + * the security server function security_net_peersid_cmp(). The function + * returns zero if the value in @sid is valid (although it may be SECSID_NULL) + * or -EACCES if @sid is invalid due to inconsistencies with the different + * peer labels. * */ -static void selinux_skb_extlbl_sid(struct sk_buff *skb, - u16 family, - u32 *sid) +static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) { u32 xfrm_sid; u32 nlbl_sid; + u32 nlbl_type; selinux_skb_xfrm_sid(skb, &xfrm_sid); - if (selinux_netlbl_skbuff_getsid(skb, -family, -(xfrm_sid == SECSID_NULL ? - SECINITSID_NETMSG : xfrm_sid), -&nlbl_sid) != 0) - nlbl_sid = SECSID_NULL; - *sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid); + selinux_netlbl_skbuff_getsid(skb, +family, +SECINITSID_NETMSG, +&nlbl_type, +&nlbl_sid); + + if (security_net_peersid_resolve(nlbl_sid, nlbl_type, +xfrm_sid, +sid) != 0) + return -EACCES; + + return 0; } /* socket security operations */ @@ -3285,6 +3288,7 @@ static int selinux_socket_post_create(struct socket *sock, int family, if (sock->sk) { sksec = sock->sk->sk_security; sksec->sid = isec->sid; + sksec->sclass = isec->sclass; err = selinux_netlbl_socket_post_create(sock); } @@ -3588,132 +3592,154 @@ static int selinux_socket_unix_may_send(struct socket *sock, return 0; } -static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, - struct avc_audit_data *ad, u16 family, char *addrp, int len) +static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk, + struct sk_buff *skb, + struct avc_audit_data *ad, + u16 family, + char *addrp, + int len) { - int err = 0; - u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0; - struct socket *sock; - u16 sock_class = 0; - u32 sock_sid = 0; - - 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
[RFC PATCH v7 07/13] SELinux: Add a capabilities bitmap to SELinux policy version 22
Add a new policy capabilities bitmap to SELinux policy version 22. This bitmap will enable the security server to query the policy to determine which features it supports. --- security/selinux/Kconfig|2 - security/selinux/include/security.h | 15 ++ security/selinux/selinuxfs.c| 89 +-- security/selinux/ss/policydb.c | 18 +++ security/selinux/ss/policydb.h |2 + security/selinux/ss/services.c | 67 ++ 6 files changed, 185 insertions(+), 8 deletions(-) diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index b32a459..2b517d6 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig @@ -145,7 +145,7 @@ config SECURITY_SELINUX_POLICYDB_VERSION_MAX config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE int "NSA SELinux maximum supported policy format version value" depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX - range 15 21 + range 15 22 default 19 help This option sets the value for the maximum policy format version diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 39337af..4d3c0d3 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -25,13 +25,14 @@ #define POLICYDB_VERSION_MLS 19 #define POLICYDB_VERSION_AVTAB 20 #define POLICYDB_VERSION_RANGETRANS21 +#define POLICYDB_VERSION_POLCAP22 /* Range of policy versions we understand*/ #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE #else -#define POLICYDB_VERSION_MAX POLICYDB_VERSION_RANGETRANS +#define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP #endif struct netlbl_lsm_secattr; @@ -39,8 +40,19 @@ struct netlbl_lsm_secattr; extern int selinux_enabled; extern int selinux_mls_enabled; +/* Policy capabilities */ +enum { + POLICYDB_CAPABILITY_NETPEER, + __POLICYDB_CAPABILITY_MAX +}; +#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1) + +extern int selinux_policycap_netpeer; + int security_load_policy(void * data, size_t len); +int security_policycap_supported(unsigned int req_cap); + #define SEL_VEC_MAX 32 struct av_decision { u32 allowed; @@ -92,6 +104,7 @@ int security_get_classes(char ***classes, int *nclasses); int security_get_permissions(char *class, char ***perms, int *nperms); int security_get_reject_unknown(void); int security_get_allow_unknown(void); +int security_get_policycaps(int *len, int **values); #define SECURITY_FS_USE_XATTR 1 /* use xattr */ #define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */ diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index f5f3e6d..cf583cc 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -2,6 +2,11 @@ * * Added conditional policy language extensions * + * Updated: Hewlett-Packard <[EMAIL PROTECTED]> + * + * Added support for the policy capability bitmap + * + * Copyright (C) 2007 Hewlett-Packard Development Company, L.P. * Copyright (C) 2003 - 2004 Tresys Technology, LLC * Copyright (C) 2004 Red Hat, Inc., James Morris <[EMAIL PROTECTED]> * This program is free software; you can redistribute it and/or modify @@ -35,6 +40,11 @@ #include "objsec.h" #include "conditional.h" +/* Policy capability filenames */ +static char *policycap_names[] = { + "network_peer_controls" +}; + unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; #ifdef CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT @@ -71,6 +81,9 @@ static int *bool_pending_values = NULL; static struct dentry *class_dir = NULL; static unsigned long last_class_ino; +/* global data for policy capabilities */ +static struct dentry *policycap_dir = NULL; + extern void selnl_notify_setenforce(int val); /* Check whether a task is allowed to use a security operation. */ @@ -110,10 +123,11 @@ enum sel_inos { static unsigned long sel_last_ino = SEL_INO_NEXT - 1; -#define SEL_INITCON_INO_OFFSET 0x0100 -#define SEL_BOOL_INO_OFFSET0x0200 -#define SEL_CLASS_INO_OFFSET 0x0400 -#define SEL_INO_MASK 0x00ff +#define SEL_INITCON_INO_OFFSET 0x0100 +#define SEL_BOOL_INO_OFFSET0x0200 +#define SEL_CLASS_INO_OFFSET 0x0400 +#define SEL_POLICYCAP_INO_OFFSET 0x0800 +#define SEL_INO_MASK 0x00ff #define TMPBUFLEN 12 static ssize_t sel_read_enforce(struct file *filp, char __user *buf, @@ -262,6 +276,7 @@ static const struct file_operations sel_policyvers_ops = { /* declaration for sel_write_load */ static int sel_make_bools(void); static int sel_make_classes(void); +static int sel_make_po
[RFC PATCH v7 06/13] NetLabel: add IP address family information to the netlbl_skbuff_getattr() function
In order to do any sort of IP header inspection of incoming packets we need to know which address family, AF_INET/AF_INET6/etc., it belongs to and since the sk_buff structure does not store this information we need to pass along the address family separate from the packet itself. --- include/net/netlabel.h |2 ++ net/netlabel/netlabel_kapi.c|2 ++ security/selinux/hooks.c| 24 ++-- security/selinux/include/netlabel.h |8 +++- security/selinux/netlabel.c | 12 +--- 5 files changed, 38 insertions(+), 10 deletions(-) diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 18b73cf..a3bffb4 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -363,6 +363,7 @@ int netlbl_sock_setattr(struct sock *sk, int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr); int netlbl_skbuff_getattr(const struct sk_buff *skb, + u16 family, struct netlbl_lsm_secattr *secattr); void netlbl_skbuff_err(struct sk_buff *skb, int error); @@ -415,6 +416,7 @@ static inline int netlbl_sock_getattr(struct sock *sk, return -ENOSYS; } static inline int netlbl_skbuff_getattr(const struct sk_buff *skb, + u16 family, struct netlbl_lsm_secattr *secattr) { return -ENOSYS; diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index d3762ea..4914615 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -332,6 +332,7 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) /** * netlbl_skbuff_getattr - Determine the security attributes of a packet * @skb: the packet + * @family: protocol family * @secattr: the security attributes * * Description: @@ -342,6 +343,7 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) * */ int netlbl_skbuff_getattr(const struct sk_buff *skb, + u16 family, struct netlbl_lsm_secattr *secattr) { if (CIPSO_V4_OPTEXIST(skb) && diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8bb673b..2188b9c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3192,6 +3192,7 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, /** * selinux_skb_extlbl_sid - Determine the external label of a packet * @skb: the packet + * @family: protocol family * @sid: the packet's SID * * Description: @@ -3204,13 +3205,16 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, * selinux_netlbl_skbuff_getsid(). * */ -static void selinux_skb_extlbl_sid(struct sk_buff *skb, u32 *sid) +static void selinux_skb_extlbl_sid(struct sk_buff *skb, + u16 family, + u32 *sid) { u32 xfrm_sid; u32 nlbl_sid; selinux_skb_xfrm_sid(skb, &xfrm_sid); if (selinux_netlbl_skbuff_getsid(skb, +family, (xfrm_sid == SECSID_NULL ? SECINITSID_NETMSG : xfrm_sid), &nlbl_sid) != 0) @@ -3703,7 +3707,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) if (err) goto out; - err = selinux_netlbl_sock_rcv_skb(sksec, skb, &ad); + err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad); if (err) goto out; @@ -3760,11 +3764,19 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff * { u32 peer_secid = SECSID_NULL; int err = 0; + u16 family; + + if (sock) + family = sock->sk->sk_family; + else if (skb->sk) + family = skb->sk->sk_family; + else + family = PF_UNSPEC; - if (sock && sock->sk->sk_family == PF_UNIX) + if (sock && family == PF_UNIX) selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); else if (skb) - selinux_skb_extlbl_sid(skb, &peer_secid); + selinux_skb_extlbl_sid(skb, family, &peer_secid); if (peer_secid == SECSID_NULL) err = -EINVAL; @@ -3825,7 +3837,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, u32 newsid; u32 peersid; - selinux_skb_extlbl_sid(skb, &peersid); + selinux_skb_extlbl_sid(skb, sk->sk_family, &peersid); if (peersid == SECSID_NULL) { req->secid = sksec->sid; req->peer_secid = SECSID_NULL; @@ -3863,7 +3875,7 @@ static void selinux_inet_conn_established(struct sock *sk, { struct sk_security_struct *sksec = sk->sk_security;
[RFC PATCH v7 12/13] NetLabel: introduce static network labels for unlabeled connections
Most trusted OSs, with the exception of Linux, have the ability to specify static security labels for unlabeled networks. This patch adds this ability to the NetLabel packet labeling framework. If the NetLabel subsystem is called to determine the security attributes of an incoming packet it first checks to see if any recognized NetLabel packet labeling protocols are in-use on the packet. If none can be found then the unlabled connection table is queried and based on the packets incoming interface and address it is matched with a security label as configured by the administrator using the netlabel_tools package. The matching security label is returned to the caller just as if the packet was explicitly labeled using a labeling protocol. --- include/net/netlabel.h|6 net/netlabel/netlabel_kapi.c | 16 net/netlabel/netlabel_unlabeled.c | 1373 + net/netlabel/netlabel_unlabeled.h | 145 4 files changed, 1522 insertions(+), 18 deletions(-) diff --git a/include/net/netlabel.h b/include/net/netlabel.h index a3bffb4..b3213c7 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -67,7 +67,11 @@ * NetLabel NETLINK protocol */ -#define NETLBL_PROTO_VERSION1 +/* NetLabel NETLINK protocol version + * 1: initial version + * 2: added static labels for unlabeled connections + */ +#define NETLBL_PROTO_VERSION2 /* NetLabel NETLINK types/families */ #define NETLBL_NLTYPE_NONE 0 diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 4914615..c69e3e1 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -312,7 +312,7 @@ socket_setattr_return: * @secattr: the security attributes * * Description: - * Examines the given sock to see any NetLabel style labeling has been + * Examines the given sock to see if any NetLabel style labeling has been * applied to the sock, if so it parses the socket label and returns the * security attributes in @secattr. Returns zero on success, negative values * on failure. @@ -320,13 +320,7 @@ socket_setattr_return: */ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) { - int ret_val; - - ret_val = cipso_v4_sock_getattr(sk, secattr); - if (ret_val == 0) - return 0; - - return netlbl_unlabel_getattr(secattr); + return cipso_v4_sock_getattr(sk, secattr); } /** @@ -350,7 +344,7 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb, cipso_v4_skbuff_getattr(skb, secattr) == 0) return 0; - return netlbl_unlabel_getattr(secattr); + return netlbl_unlabel_getattr(skb, family, secattr); } /** @@ -434,6 +428,10 @@ static int __init netlbl_init(void) if (ret_val != 0) goto init_failure; + ret_val = netlbl_unlabel_init(NETLBL_UNLHSH_BITSIZE); + if (ret_val != 0) + goto init_failure; + ret_val = netlbl_netlink_init(); if (ret_val != 0) goto init_failure; diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 5e11394..add0988 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -10,7 +10,7 @@ */ /* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 + * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - 2007 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,22 +36,88 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include #include #include - +#include +#include #include #include +#include #include "netlabel_user.h" #include "netlabel_domainhash.h" #include "netlabel_unlabeled.h" +#include "netlabel_mgmt.h" + +/* The unlabeled connection hash table which we use to map network interfaces + * and addresses of unlabeled packets to a user specified secid value for the + * LSM. The hash table is used to lookup the network interface entry + * (struct netlbl_unlhsh_iface) and then the interface entry is used to + * lookup an IP address match from an ordered list. If a network interface + * match can not be found in the hash table then the default entry + * (netlbl_unlhsh_def) is used. The IP address entry list + * (struct netlbl_unlhsh_addr) is ordered such that the entries with a + * larger netmask come first. + */ +struct netlbl_unlhsh_tbl { + struct list_head *tbl; + u32 size; +}; +struct netlbl_unlhsh_addr4 { + __be32 addr; + __be32 mask; + u32 secid; + + u32 valid; + struct list_head list; + struct rcu_head rcu; +}; +struct netlbl_unlhsh_addr6 { + struct in6_addr addr; + struct in6_addr mask; + u32 secid; + + u32 valid; + struct list_head list; +
Re: [TOMOYO #5 18/18] LSM expansion for TOMOYO Linux.
On Friday 16 November 2007 12:34:57 pm [EMAIL PROTECTED] wrote: > LSM hooks for network accept and recv: >* socket_post_accept is modified to return int. >* post_recv_datagram is added in skb_recv_datagram. > > You can try TOMOYO Linux without this patch, but in that case, you > can't use access control functionality for restricting signal > transmission and incoming network data. As discussed a few times before, I'm still not really excited about adding a new LSM hook in skb_recv_datagram() when we already have hooks to control locally consumed network traffic. However, I will admit that these existing hooks do not allow the LSM to block and query userspace for an access decision like you are trying to do with TOMOYO. I would prefer not to see this new LSM hook added but I do not have an alternative solution to your problem so I can't in good conscience completely object to this patch. Regardless, I have a few comments which are included below ... > --- linux-2.6-mm.orig/net/core/datagram.c 2007-10-10 05:31:38.0 > +0900 +++ linux-2.6-mm/net/core/datagram.c2007-11-14 15:15:44.0 > +0900 @@ -55,6 +55,7 @@ > #include > #include > #include > +#include > > /* > * Is a socket 'connection oriented' ? > @@ -178,6 +179,27 @@ struct sk_buff *skb_recv_datagram(struct > } else > skb = skb_dequeue(&sk->sk_receive_queue); > > + error = security_post_recv_datagram(sk, skb, flags); > + if (error) { > + unsigned long cpu_flags; With this patch the 'cpu_flags' variable will be used in two different if-blocks in this function and declared locally within each block. Please move the 'cpu_flags' declaration to the top of the function so it only needs to be declared once. > + > + if (!(flags & MSG_PEEK)) > + goto no_peek; > + > + spin_lock_irqsave(&sk->sk_receive_queue.lock, > + cpu_flags); > + if (skb == skb_peek(&sk->sk_receive_queue)) { I might be missing something here, but why do you need to do a skb_peek() again? You already have the skb and the sock, just do the unlink. > + __skb_unlink(skb, > + &sk->sk_receive_queue); > + atomic_dec(&skb->users); > + } > + spin_unlock_irqrestore(&sk->sk_receive_queue.lock, > +cpu_flags); > +no_peek: > + skb_free_datagram(sk, skb); > + goto no_packet; Two things. First you can probably just call kfree_skb() instead of skb_free_datagram(). Second, why not move the 'no_peek' code to just before 'no_packet'? -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [TOMOYO #5 18/18] LSM expansion for TOMOYO Linux.
On Friday 16 November 2007 10:45:32 pm Tetsuo Handa wrote: > Paul Moore wrote: > > I might be missing something here, but why do you need to do a skb_peek() > > again? You already have the skb and the sock, just do the unlink. > > The skb might be already dequeued by other thread while I slept inside > security_post_recv_datagram(). Okay, well if that is the case I think you are going to have another problem in that you could end up throwing away skbs that haven't been through your security_post_recv_datagram() hook because you _always_ throw away the result of the second skb_peek(). Once again, if I'm wrong please correct me. > > Second, why not move the 'no_peek' code to just before 'no_packet'? > > Oh, I didn't notice I can insert here. Now I can also move the rest code > like > > | error = security_post_recv_datagram(sk, skb, flags); > | if (error) > | goto force_dequeue; > | > | } while (!wait_for_packet(sk, err, &timeo)); Where did the 'if (skb) return skb;' code go? Don't you need to do you LSM call before you return the skb? -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [TOMOYO #5 18/18] LSM expansion for TOMOYO Linux.
On Saturday 17 November 2007 11:00:20 pm Tetsuo Handa wrote: > Hello. Hello. > Paul Moore wrote: > > Okay, well if that is the case I think you are going to have another > > problem in that you could end up throwing away skbs that haven't been > > through your security_post_recv_datagram() hook because you _always_ > > throw away the result of the second skb_peek(). Once again, if I'm wrong > > please correct me. > > I didn't understand what's wrong with throwing away the result of > the second skb_peek(). My concern is that you stated earlier that you needed to do the second skb_peek() because the first skb may have been removed from the socket queue while your LSM was making an access decision in security_post_recv_datagram(). If that is the case then the second call to skb_peek() will return a different skb then the one you passed to security_post_recv_datagram(). This is significant because you always throw away this second skb without first consulting the LSM via security_post_recv_datagram(). -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [TOMOYO #5 18/18] LSM expansion for TOMOYO Linux.
On Monday 19 November 2007 9:29:52 am Tetsuo Handa wrote: > Paul Moore wrote: > > If that is the case then the second call to > > skb_peek() will return a different skb then the one you passed to > > security_post_recv_datagram(). > > Yes. The second call to skb_peek() might return a different skb than the > one I passed to security_post_recv_datagram(). My apologies, I mistakenly read the following if statement in your patch: +Â Â Â if (skb == skb_peek(&sk->sk_receive_queue)) { +Â Â Â __skb_unlink(skb, &sk->sk_receive_queue); +Â Â Â atomic_dec(&skb->users); +Â Â Â } I read the conditional as the following: + if (skb = skb_peek(&sk->sk_receive_queue)) { ... which would have caused the problems I was describing. I'm sorry for all of the confusion/frustration, you patient explanations are correct; I was wrong in this particular case. -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v8 18/18] SELinux: Add network ingress and egress control permission checks
This patch implements packet ingress/egress controls for SELinux which allow SELinux security policy to control the flow of all IPv4 and IPv6 packets into and out of the system. Currently SELinux does not have proper control over forwarded packets and this patch corrects this problem. Special thanks to Venkat Yekkirala <[EMAIL PROTECTED]> whose earlier work on this topic eventually led to this patch. --- security/selinux/hooks.c | 335 +++--- 1 files changed, 228 insertions(+), 107 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 2f221b2..2a6d50f 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -12,8 +12,8 @@ * Copyright (C) 2003 Red Hat, Inc., James Morris <[EMAIL PROTECTED]> * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * <[EMAIL PROTECTED]> - * Copyright (C) 2006 Hewlett-Packard Development Company, L.P. - * Paul Moore, <[EMAIL PROTECTED]> + * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. + * Paul Moore <[EMAIL PROTECTED]> * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd. * Yuichi Nakamura <[EMAIL PROTECTED]> * @@ -3608,6 +3608,71 @@ static int selinux_socket_unix_may_send(struct socket *sock, return 0; } +static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, + u32 peer_sid, + struct avc_audit_data *ad) +{ + int err; + u32 if_sid; + u32 node_sid; + + err = sel_netif_sid(ifindex, &if_sid); + if (err) + return err; + err = avc_has_perm(if_sid, peer_sid, SECCLASS_PEER, PEER__INGRESS, ad); + if (err) + return err; + + err = sel_netnode_sid(addrp, family, &node_sid); + if (err) + return err; + return avc_has_perm(node_sid, peer_sid, + SECCLASS_PEER, PEER__INGRESS, ad); +} + +static int selinux_inet_sys_snd_skb(struct sk_buff *skb, int family) +{ + int err = 0; + + if (!selinux_policycap_netpeer) + return 0; + + if (netlbl_enabled() || selinux_xfrm_enabled()) { + u32 if_sid; + u32 node_sid; + u32 peer_sid; + char *addrp; + struct avc_audit_data ad; + + AVC_AUDIT_DATA_INIT(&ad, NET); + ad.u.net.netif = skb->iif; + ad.u.net.family = family; + err = selinux_parse_skb(skb, &ad, &addrp, 0, NULL); + if (err) + return err; + + err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); + if (err) + return err; + + err = sel_netif_sid(skb->iif, &if_sid); + if (err) + return err; + err = avc_has_perm(if_sid, peer_sid, + SECCLASS_PEER, PEER__EGRESS, &ad); + if (err) + return err; + + err = sel_netnode_sid(addrp, family, &node_sid); + if (err) + return err; + err = avc_has_perm(node_sid, peer_sid, + SECCLASS_PEER, PEER__EGRESS, &ad); + } + + return err; +} + static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk, struct sk_buff *skb, struct avc_audit_data *ad, @@ -3748,6 +3813,10 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); if (err) return err; + err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family, + peer_sid, &ad); + if (err) + return err; err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, PEER__RECV, &ad); } @@ -3965,151 +4034,175 @@ out: #ifdef CONFIG_NETFILTER -static int selinux_ip_postroute_last_compat(struct sock *sk, - struct net_device *dev, - struct avc_audit_data *ad, - u16 family, - char *addrp) +static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, + u16 family) { - int err = 0; - u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0; - struct socket *sock; - struct inode *inode; - struct inod
[RFC PATCH v8 05/18] LSM: Add secctx_to_secid() LSM hook
Add a secctx_to_secid() LSM hook to go along with the existing secid_to_secctx() LSM hook. This patch also includes the SELinux implementation for this hook. --- include/linux/security.h | 13 + security/dummy.c |6 ++ security/security.c |6 ++ security/selinux/hooks.c |6 ++ 4 files changed, 31 insertions(+), 0 deletions(-) diff --git a/include/linux/security.h b/include/linux/security.h index ac05083..db19c92 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1183,6 +1183,10 @@ struct request_sock; * Convert secid to security context. * @secid contains the security ID. * @secdata contains the pointer that stores the converted security context. + * @secctx_to_secid: + * Convert security context to secid. + * @secid contains the pointer to the generated security ID. + * @secdata contains the security context. * * @release_secctx: * Release the security context. @@ -1371,6 +1375,7 @@ struct security_operations { int (*getprocattr)(struct task_struct *p, char *name, char **value); int (*setprocattr)(struct task_struct *p, char *name, void *value, size_t size); int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen); + int (*secctx_to_secid)(char *secdata, u32 seclen, u32 *secid); void (*release_secctx)(char *secdata, u32 seclen); #ifdef CONFIG_SECURITY_NETWORK @@ -1603,6 +1608,7 @@ int security_setprocattr(struct task_struct *p, char *name, void *value, size_t int security_netlink_send(struct sock *sk, struct sk_buff *skb); int security_netlink_recv(struct sk_buff *skb, int cap); int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); +int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid); void security_release_secctx(char *secdata, u32 seclen); #else /* CONFIG_SECURITY */ @@ -2280,6 +2286,13 @@ static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *secle return -EOPNOTSUPP; } +static inline int security_secctx_to_secid(char *secdata, + u32 seclen, + u32 *secid) +{ + return -EOPNOTSUPP; +} + static inline void security_release_secctx(char *secdata, u32 seclen) { } diff --git a/security/dummy.c b/security/dummy.c index 3ccfbbe..0b62f95 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -928,6 +928,11 @@ static int dummy_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) return -EOPNOTSUPP; } +static int dummy_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) +{ + return -EOPNOTSUPP; +} + static void dummy_release_secctx(char *secdata, u32 seclen) { } @@ -1086,6 +1091,7 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, getprocattr); set_to_dummy_if_null(ops, setprocattr); set_to_dummy_if_null(ops, secid_to_secctx); + set_to_dummy_if_null(ops, secctx_to_secid); set_to_dummy_if_null(ops, release_secctx); #ifdef CONFIG_SECURITY_NETWORK set_to_dummy_if_null(ops, unix_stream_connect); diff --git a/security/security.c b/security/security.c index 0e1f1f1..3bdcada 100644 --- a/security/security.c +++ b/security/security.c @@ -816,6 +816,12 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) } EXPORT_SYMBOL(security_secid_to_secctx); +int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) +{ + return security_ops->secctx_to_secid(secdata, seclen, secid); +} +EXPORT_SYMBOL(security_secctx_to_secid); + void security_release_secctx(char *secdata, u32 seclen) { return security_ops->release_secctx(secdata, seclen); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 9f3124b..8bb673b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4710,6 +4710,11 @@ static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) return security_sid_to_context(secid, secdata, seclen); } +static int selinux_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) +{ + return security_context_to_sid(secdata, seclen, secid); +} + static void selinux_release_secctx(char *secdata, u32 seclen) { kfree(secdata); @@ -4898,6 +4903,7 @@ static struct security_operations selinux_ops = { .setprocattr = selinux_setprocattr, .secid_to_secctx = selinux_secid_to_secctx, + .secctx_to_secid = selinux_secctx_to_secid, .release_secctx = selinux_release_secctx, .unix_stream_connect = selinux_socket_unix_stream_connect, - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v8 09/18] SELinux: Only store the network interface's ifindex
Instead of storing the packet's network interface name store the ifindex. This allows us to defer the need to lookup the net_device structure until the audit record is generated meaning that in the majority of cases we never need to bother with this at all. --- security/selinux/avc.c | 15 --- security/selinux/hooks.c |4 ++-- security/selinux/include/avc.h |7 +-- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 81b3dff..8ecfab9 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -661,9 +661,18 @@ void avc_audit(u32 ssid, u32 tsid, "daddr", "dest"); break; } - if (a->u.net.netif) - audit_log_format(ab, " netif=%s", - a->u.net.netif); + if (a->u.net.netif >= 0) { + struct net_device *dev; + + /* NOTE: we always use init's namespace */ + dev = dev_get_by_index(&init_net, + a->u.net.netif); + if (dev) { + audit_log_format(ab, " netif=%s", +dev->name); + dev_put(dev); + } + } break; } } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 2ca8dfb..e429a8c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3691,7 +3691,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) family = PF_INET; AVC_AUDIT_DATA_INIT(&ad, NET); - ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]"; + ad.u.net.netif = skb->iif; ad.u.net.family = family; err = selinux_parse_skb(skb, &ad, &addrp, &len, 1, NULL); @@ -4023,7 +4023,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum, sksec = sk->sk_security; AVC_AUDIT_DATA_INIT(&ad, NET); - ad.u.net.netif = dev->name; + ad.u.net.netif = dev->ifindex; ad.u.net.family = family; err = selinux_parse_skb(skb, &ad, &addrp, &len, 0, &proto); diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 553607a..5185152 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -51,7 +51,7 @@ struct avc_audit_data { struct inode *inode; } fs; struct { - char *netif; + int netif; struct sock *sk; u16 family; __be16 dport; @@ -77,7 +77,10 @@ struct avc_audit_data { /* Initialize an AVC audit data structure. */ #define AVC_AUDIT_DATA_INIT(_d,_t) \ -{ memset((_d), 0, sizeof(struct avc_audit_data)); (_d)->type = AVC_AUDIT_DATA_##_t; } +{ memset((_d), 0, sizeof(struct avc_audit_data)); \ + (_d)->type = AVC_AUDIT_DATA_##_t; \ + if ((_d)->type == AVC_AUDIT_DATA_NET) \ + (_d)->u.net.netif = -1; } /* * AVC statistics - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v8 12/18] SELinux: Add new peer permissions to the Flask definitions
Add additional Flask definitions to support the new "peer" object class. --- security/selinux/include/av_perm_to_string.h |3 +++ security/selinux/include/av_permissions.h|3 +++ security/selinux/include/class_to_string.h |7 +++ security/selinux/include/flask.h |1 + 4 files changed, 14 insertions(+), 0 deletions(-) diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h index 049bf69..458b6aa 100644 --- a/security/selinux/include/av_perm_to_string.h +++ b/security/selinux/include/av_perm_to_string.h @@ -159,3 +159,6 @@ S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind") S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect") S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero") + S_(SECCLASS_PEER, PEER__INGRESS, "ingress") + S_(SECCLASS_PEER, PEER__EGRESS, "egress") + S_(SECCLASS_PEER, PEER__RECV, "recv") diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h index eda89a2..861a77d 100644 --- a/security/selinux/include/av_permissions.h +++ b/security/selinux/include/av_permissions.h @@ -824,3 +824,6 @@ #define DCCP_SOCKET__NODE_BIND0x0040UL #define DCCP_SOCKET__NAME_CONNECT 0x0080UL #define MEMPROTECT__MMAP_ZERO 0x0001UL +#define PEER__INGRESS 0x0001UL +#define PEER__EGRESS 0x0002UL +#define PEER__RECV0x0004UL diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h index e77de0e..b1b0d1d 100644 --- a/security/selinux/include/class_to_string.h +++ b/security/selinux/include/class_to_string.h @@ -64,3 +64,10 @@ S_(NULL) S_("dccp_socket") S_("memprotect") +S_(NULL) +S_(NULL) +S_(NULL) +S_(NULL) +S_(NULL) +S_(NULL) +S_("peer") diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h index a9c2b20..09e9dd2 100644 --- a/security/selinux/include/flask.h +++ b/security/selinux/include/flask.h @@ -50,6 +50,7 @@ #define SECCLASS_KEY 58 #define SECCLASS_DCCP_SOCKET 60 #define SECCLASS_MEMPROTECT 61 +#define SECCLASS_PEER68 /* * Security identifier indices for initial entities - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v8 02/18] NetLabel: Cleanup the LSM domain hash functions
The NetLabel/LSM domain hash table search function used an argument to specify if the default entry should be returned if an exact match couldn't be found in the hash table. This is a bit against the kernel's style so make two separate functions to represent the separate behaviors. --- net/netlabel/netlabel_domainhash.c | 47 ++-- 1 files changed, 34 insertions(+), 13 deletions(-) diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index b3675bd..1f8f7ac 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c @@ -109,17 +109,14 @@ static u32 netlbl_domhsh_hash(const char *key) /** * netlbl_domhsh_search - Search for a domain entry * @domain: the domain - * @def: return default if no match is found * * Description: * Searches the domain hash table and returns a pointer to the hash table - * entry if found, otherwise NULL is returned. If @def is non-zero and a - * match is not found in the domain hash table the default mapping is returned - * if it exists. The caller is responsibile for the rcu hash table locks - * (i.e. the caller much call rcu_read_[un]lock()). + * entry if found, otherwise NULL is returned. The caller is responsibile for + * the rcu hash table locks (i.e. the caller much call rcu_read_[un]lock()). * */ -static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain, u32 def) +static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain) { u32 bkt; struct netlbl_dom_map *iter; @@ -133,10 +130,31 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain, u32 def) return iter; } - if (def != 0) { - iter = rcu_dereference(netlbl_domhsh_def); - if (iter != NULL && iter->valid) - return iter; + return NULL; +} + +/** + * netlbl_domhsh_search_def - Search for a domain entry + * @domain: the domain + * @def: return default if no match is found + * + * Description: + * Searches the domain hash table and returns a pointer to the hash table + * entry if an exact match is found, if an exact match is not present in the + * hash table then the default entry is returned if valid otherwise NULL is + * returned. The caller is responsibile for the rcu hash table locks + * (i.e. the caller much call rcu_read_[un]lock()). + * + */ +static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain) +{ + struct netlbl_dom_map *entry; + + entry = netlbl_domhsh_search(domain); + if (entry == NULL) { + entry = rcu_dereference(netlbl_domhsh_def); + if (entry != NULL && entry->valid) + return entry; } return NULL; @@ -224,7 +242,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, if (entry->domain != NULL) { bkt = netlbl_domhsh_hash(entry->domain); spin_lock(&netlbl_domhsh_lock); - if (netlbl_domhsh_search(entry->domain, 0) == NULL) + if (netlbl_domhsh_search(entry->domain) == NULL) list_add_tail_rcu(&entry->list, &rcu_dereference(netlbl_domhsh)->tbl[bkt]); else @@ -307,7 +325,10 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) struct audit_buffer *audit_buf; rcu_read_lock(); - entry = netlbl_domhsh_search(domain, (domain != NULL ? 0 : 1)); + if (domain) + entry = netlbl_domhsh_search(domain); + else + entry = netlbl_domhsh_search_def(domain); if (entry == NULL) goto remove_return; switch (entry->type) { @@ -377,7 +398,7 @@ int netlbl_domhsh_remove_default(struct netlbl_audit *audit_info) */ struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain) { - return netlbl_domhsh_search(domain, 1); + return netlbl_domhsh_search_def(domain); } /** - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v8 15/18] SELinux: Allow NetLabel to directly cache SIDs
Now that the SELinux NetLabel "base SID" is always the netmsg initial SID we can do a big optimization - caching the SID and not just the MLS attributes. This not only saves a lot of per-packet memory allocations and copies but it has a nice side effect of removing a chunk of code. --- security/selinux/hooks.c|6 -- security/selinux/include/netlabel.h |2 - security/selinux/include/security.h |2 - security/selinux/netlabel.c | 55 ++-- security/selinux/ss/services.c | 124 ++- 5 files changed, 55 insertions(+), 134 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index c384949..2f221b2 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3231,11 +3231,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) u32 nlbl_type; selinux_skb_xfrm_sid(skb, &xfrm_sid); - selinux_netlbl_skbuff_getsid(skb, -family, -SECINITSID_NETMSG, -&nlbl_type, -&nlbl_sid); + selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid); if (security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index c8c05a6..00a2809 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h @@ -48,7 +48,6 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, -u32 base_sid, u32 *type, u32 *sid); @@ -89,7 +88,6 @@ static inline void selinux_netlbl_sk_security_clone( static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, - u32 base_sid, u32 *type, u32 *sid) { diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 9347e2d..23137c1 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -124,7 +124,6 @@ int security_genfs_sid(const char *fstype, char *name, u16 sclass, #ifdef CONFIG_NETLABEL int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, - u32 base_sid, u32 *sid); int security_netlbl_sid_to_secattr(u32 sid, @@ -132,7 +131,6 @@ int security_netlbl_sid_to_secattr(u32 sid, #else static inline int security_netlbl_secattr_to_sid( struct netlbl_lsm_secattr *secattr, - u32 base_sid, u32 *sid) { return -EIDRM; diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index af78cb9..e07adf9 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -36,6 +36,33 @@ #include "security.h" /** + * selinux_netlbl_sidlookup_cached - Cache a SID lookup + * @skb: the packet + * @secattr: the NetLabel security attributes + * @sid: the SID + * + * Description: + * Query the SELinux security server to lookup the correct SID for the given + * security attributes. If the query is successful, cache the result to speed + * up future lookups. Returns zero on success, negative values on failure. + * + */ +static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, + struct netlbl_lsm_secattr *secattr, + u32 *sid) +{ + int rc; + + rc = security_netlbl_secattr_to_sid(secattr, sid); + if (rc == 0 && + (secattr->flags & NETLBL_SECATTR_CACHEABLE) && + (secattr->flags & NETLBL_SECATTR_CACHE)) + netlbl_cache_add(skb, secattr); + + return rc; +} + +/** * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism * @sk: the socket to label * @sid: the SID to use @@ -141,7 +168,6 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel * @skb: the packet * @family: protocol family - * @base_sid: the SELinux SID to use as a context for MLS only attributes * @type: NetLabel labeling protocol type * @sid: the SID * @@ -153,7 +179,6 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, */ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, -u3
[RFC PATCH v8 17/18] NetLabel: Add auditing to the static labeling mechanism
This patch adds auditing support to the NetLabel static labeling mechanism. --- include/linux/audit.h |2 net/netlabel/netlabel_unlabeled.c | 207 ++--- 2 files changed, 195 insertions(+), 14 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index c687816..bdd6f5d 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -115,6 +115,8 @@ #define AUDIT_MAC_IPSEC_ADDSPD 1413/* Not used */ #define AUDIT_MAC_IPSEC_DELSPD 1414/* Not used */ #define AUDIT_MAC_IPSEC_EVENT 1415/* Audit an IPSec event */ +#define AUDIT_MAC_UNLBL_STCADD 1416/* NetLabel: add a static label */ +#define AUDIT_MAC_UNLBL_STCDEL 1417/* NetLabel: del a static label */ #define AUDIT_FIRST_KERN_ANOM_MSG 1700 #define AUDIT_LAST_KERN_ANOM_MSG1799 diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index d289ff4..cdeb6d9 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -148,6 +148,74 @@ static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1 }; /* + * Audit Helper Functions + */ + +/** + * netlbl_unlabel_audit_addr4 - Audit an IPv4 address + * @audit_buf: audit buffer + * @dev: network interface + * @addr: IP address + * @mask: IP address mask + * + * Description: + * Write the IPv4 address and address mask, if necessary, to @audit_buf. + * + */ +static void netlbl_unlabel_audit_addr4(struct audit_buffer *audit_buf, +const char *dev, +__be32 addr, __be32 mask) +{ + u32 mask_val = ntohl(mask); + + if (dev != NULL) + audit_log_format(audit_buf, " netif=%s", dev); + audit_log_format(audit_buf, " src=" NIPQUAD_FMT, NIPQUAD(addr)); + if (mask_val != 0x) { + u32 mask_len = 0; + while (mask_val > 0) { + mask_val <<= 1; + mask_len++; + } + audit_log_format(audit_buf, " src_prefixlen=%d", mask_len); + } +} + +/** + * netlbl_unlabel_audit_addr6 - Audit an IPv6 address + * @audit_buf: audit buffer + * @dev: network interface + * @addr: IP address + * @mask: IP address mask + * + * Description: + * Write the IPv6 address and address mask, if necessary, to @audit_buf. + * + */ +static void netlbl_unlabel_audit_addr6(struct audit_buffer *audit_buf, +const char *dev, +const struct in6_addr *addr, +const struct in6_addr *mask) +{ + if (dev != NULL) + audit_log_format(audit_buf, " netif=%s", dev); + audit_log_format(audit_buf, " src=" NIP6_FMT, NIP6(*addr)); + if (ntohl(mask->s6_addr32[3]) != 0x) { + u32 mask_len = 0; + u32 mask_val; + int iter = -1; + while (ntohl(mask->s6_addr32[++iter]) == 0x) + mask_len += 32; + mask_val = ntohl(mask->s6_addr32[iter]); + while (mask_val > 0) { + mask_val <<= 1; + mask_len++; + } + audit_log_format(audit_buf, " src_prefixlen=%d", mask_len); + } +} + +/* * Unlabeled Connection Hash Table Functions */ @@ -524,6 +592,7 @@ add_iface_failure: * @mask: address mask in network byte order * @addr_len: length of address/mask (4 for IPv4, 16 for IPv6) * @secid: LSM secid value for the entry + * @audit_info: NetLabel audit information * * Description: * Adds a new entry to the unlabeled connection hash table. Returns zero on @@ -535,12 +604,18 @@ static int netlbl_unlhsh_add(struct net *net, const void *addr, const void *mask, u32 addr_len, -u32 secid) +u32 secid, +struct netlbl_audit *audit_info) { int ret_val; int ifindex; struct net_device *dev; struct netlbl_unlhsh_iface *iface; + struct in_addr *addr4, *mask4; + struct in6_addr *addr6, *mask6; + struct audit_buffer *audit_buf = NULL; + char *secctx = NULL; + u32 secctx_len; if (addr_len != sizeof(struct in_addr) && addr_len != sizeof(struct in6_addr)) @@ -567,13 +642,28 @@ static int netlbl_unlhsh_add(struct net *net, goto unlhsh_add_return; } } + audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCADD, + audit_info); switch (addr_len) { case sizeof(struct in_addr): - ret_val = netlbl_unlhsh_add_addr4(iface, addr, mask, secid); + addr4 = (struct in_addr *)addr; + mask4 = (struct in_ad
[RFC PATCH v8 04/18] NetLabel: Add secid token support to the NetLabel secattr struct
This patch adds support to the NetLabel LSM secattr struct for a secid token and a type field, paving the way for full LSM/SELinux context support and "static" or "fallback" labels. In addition, this patch adds a fair amount of documentation to the core NetLabel structures used as part of the NetLabel kernel API. --- include/net/netlabel.h| 91 ++--- net/ipv4/cipso_ipv4.c | 59 +++- net/netlabel/netlabel_unlabeled.c |1 security/selinux/ss/mls.c | 10 ++-- security/selinux/ss/services.c|5 ++ 5 files changed, 120 insertions(+), 46 deletions(-) diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 2e5b2f6..18b73cf 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -105,17 +105,49 @@ struct netlbl_dom_map; /* Domain mapping operations */ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info); -/* LSM security attributes */ +/* + * LSM security attributes + */ + +/** + * struct netlbl_lsm_cache - NetLabel LSM security attribute cache + * @refcount: atomic reference counter + * @free: LSM supplied function to free the cache data + * @data: LSM supplied cache data + * + * Description: + * This structure is provided for LSMs which wish to make use of the NetLabel + * caching mechanism to store LSM specific data/attributes in the NetLabel + * cache. If the LSM has to perform a lot of translation from the NetLabel + * security attributes into it's own internal representation then the cache + * mechanism can provide a way to eliminate some or all of that translation + * overhead on a cache hit. + * + */ struct netlbl_lsm_cache { atomic_t refcount; void (*free) (const void *data); void *data; }; -/* The catmap bitmap field MUST be a power of two in length and large + +/** + * struct netlbl_lsm_secattr_catmap - NetLabel LSM secattr category bitmap + * @startbit: the value of the lowest order bit in the bitmap + * @bitmap: the category bitmap + * @next: pointer to the next bitmap "node" or NULL + * + * Description: + * This structure is used to represent category bitmaps. Due to the large + * number of categories supported by most labeling protocols it is not + * practical to transfer a full bitmap internally so NetLabel adopts a sparse + * bitmap structure modeled after SELinux's ebitmap structure. + * The catmap bitmap field MUST be a power of two in length and large * enough to hold at least 240 bits. Special care (i.e. check the code!) * should be used when changing these values as the LSM implementation * probably has functions which rely on the sizes of these types to speed - * processing. */ + * processing. + * + */ #define NETLBL_CATMAP_MAPTYPE u64 #define NETLBL_CATMAP_MAPCNT4 #define NETLBL_CATMAP_MAPSIZE (sizeof(NETLBL_CATMAP_MAPTYPE) * 8) @@ -127,22 +159,48 @@ struct netlbl_lsm_secattr_catmap { NETLBL_CATMAP_MAPTYPE bitmap[NETLBL_CATMAP_MAPCNT]; struct netlbl_lsm_secattr_catmap *next; }; + +/** + * struct netlbl_lsm_secattr - NetLabel LSM security attributes + * @flags: indicate which attributes are contained in this structure + * @type: indicate the NLTYPE of the attributes + * @domain: the NetLabel LSM domain + * @cache: NetLabel LSM specific cache + * @attr.mls: MLS sensitivity label + * @attr.mls.cat: MLS category bitmap + * @attr.mls.lvl: MLS sensitivity level + * @attr.secid: LSM specific secid token + * + * Description: + * This structure is used to pass security attributes between NetLabel and the + * LSM modules. The flags field is used to specify which fields within the + * struct are valid and valid values can be created by bitwise OR'ing the + * NETLBL_SECATTR_* defines. The domain field is typically set by the LSM to + * specify domain specific configuration settings and is not usually used by + * NetLabel itself when returning security attributes to the LSM. + * + */ #define NETLBL_SECATTR_NONE 0x #define NETLBL_SECATTR_DOMAIN 0x0001 #define NETLBL_SECATTR_CACHE0x0002 #define NETLBL_SECATTR_MLS_LVL 0x0004 #define NETLBL_SECATTR_MLS_CAT 0x0008 +#define NETLBL_SECATTR_SECID0x0010 #define NETLBL_SECATTR_CACHEABLE(NETLBL_SECATTR_MLS_LVL | \ -NETLBL_SECATTR_MLS_CAT) +NETLBL_SECATTR_MLS_CAT | \ +NETLBL_SECATTR_SECID) struct netlbl_lsm_secattr { u32 flags; - + u32 type; char *domain; - - u32 mls_lvl; - struct netlbl_lsm_secattr_catmap *mls_cat; - struct netlbl_lsm_cache *cache; + union { + struct { + struct netlbl_lsm_secattr_catmap *cat; + u32 lvl; + } mls; + u32 secid; + } attr; }; /*
[RFC PATCH v8 01/18] NetLabel: Remove unneeded RCU read locks
This patch removes some unneeded RCU read locks as we can treat the reads as "safe" even without RCU. It also converts the NetLabel configuration refcount from a spinlock protected u32 into atomic_t to be more consistent with the rest of the kernel. --- net/netlabel/netlabel_cipso_v4.c |5 ++- net/netlabel/netlabel_kapi.c |3 +- net/netlabel/netlabel_mgmt.c | 63 ++--- net/netlabel/netlabel_mgmt.h |7 ++-- net/netlabel/netlabel_unlabeled.c | 17 ++ 5 files changed, 15 insertions(+), 80 deletions(-) diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index ba0ca8d..becf91a 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "netlabel_user.h" #include "netlabel_cipso_v4.h" @@ -421,7 +422,7 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info) break; } if (ret_val == 0) - netlbl_mgmt_protocount_inc(); + atomic_inc(&netlabel_mgmt_protocount); audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD, &audit_info); @@ -698,7 +699,7 @@ static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info) &audit_info, netlbl_cipsov4_doi_free); if (ret_val == 0) - netlbl_mgmt_protocount_dec(); + atomic_dec(&netlabel_mgmt_protocount); audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_DEL, &audit_info); diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 4f50949..d3762ea 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "netlabel_domainhash.h" #include "netlabel_unlabeled.h" @@ -262,7 +263,7 @@ int netlbl_enabled(void) /* At some point we probably want to expose this mechanism to the user * as well so that admins can toggle NetLabel regardless of the * configuration */ - return (netlbl_mgmt_protocount_value() > 0 ? 1 : 0); + return (atomic_read(&netlabel_mgmt_protocount) > 0); } /** diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index 5648337..e2258dc 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c @@ -37,14 +37,14 @@ #include #include #include +#include #include "netlabel_domainhash.h" #include "netlabel_user.h" #include "netlabel_mgmt.h" -/* NetLabel configured protocol count */ -static DEFINE_SPINLOCK(netlabel_mgmt_protocount_lock); -static u32 netlabel_mgmt_protocount = 0; +/* NetLabel configured protocol counter */ +atomic_t netlabel_mgmt_protocount = ATOMIC_INIT(0); /* Argument struct for netlbl_domhsh_walk() */ struct netlbl_domhsh_walk_arg { @@ -71,63 +71,6 @@ static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = { }; /* - * NetLabel Misc Managment Functions - */ - -/** - * netlbl_mgmt_protocount_inc - Increment the configured labeled protocol count - * - * Description: - * Increment the number of labeled protocol configurations in the current - * NetLabel configuration. Keep track of this for use in determining if - * NetLabel label enforcement should be active/enabled or not in the LSM. - * - */ -void netlbl_mgmt_protocount_inc(void) -{ - spin_lock(&netlabel_mgmt_protocount_lock); - netlabel_mgmt_protocount++; - spin_unlock(&netlabel_mgmt_protocount_lock); -} - -/** - * netlbl_mgmt_protocount_dec - Decrement the configured labeled protocol count - * - * Description: - * Decrement the number of labeled protocol configurations in the current - * NetLabel configuration. Keep track of this for use in determining if - * NetLabel label enforcement should be active/enabled or not in the LSM. - * - */ -void netlbl_mgmt_protocount_dec(void) -{ - spin_lock(&netlabel_mgmt_protocount_lock); - if (netlabel_mgmt_protocount > 0) - netlabel_mgmt_protocount--; - spin_unlock(&netlabel_mgmt_protocount_lock); -} - -/** - * netlbl_mgmt_protocount_value - Return the number of configured protocols - * - * Description: - * Return the number of labeled protocols in the current NetLabel - * configuration. This value is useful in determining if NetLabel label - * enforcement should be active/enabled or not in the LSM. - * - */ -u32 netlbl_mgmt_protocount_value(void) -{ - u32 val; - - rcu_read_lock(); - val = netlabel_mgmt_protocount; - rcu_read_unlock(); - - return val; -} - -/* * NetLabel Command Handlers */ diff --git a/net/netlabel/netlabel_mgmt.h b/net/netlabel/netlabel_mgmt.h index ccb2b39..a43bff1 100644 --- a/net/netlabel/netlabel_mgmt.h +++
[RFC PATCH v8 03/18] NetLabel: Consolidate the LSM domain mapping/hashing locks
Currently we use two separate spinlocks to protect both the hash/mapping table and the default entry. This could be considered a bit foolish because it adds complexity without offering any real performance advantage. This patch removes the dedicated default spinlock and protects the default entry with the hash/mapping table spinlock. --- net/netlabel/netlabel_domainhash.c | 30 +- 1 files changed, 9 insertions(+), 21 deletions(-) diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index 1f8f7ac..9a8ea01 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c @@ -54,9 +54,6 @@ struct netlbl_domhsh_tbl { * hash table should be okay */ static DEFINE_SPINLOCK(netlbl_domhsh_lock); static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL; - -/* Default domain mapping */ -static DEFINE_SPINLOCK(netlbl_domhsh_def_lock); static struct netlbl_dom_map *netlbl_domhsh_def = NULL; /* @@ -239,24 +236,22 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, INIT_RCU_HEAD(&entry->rcu); rcu_read_lock(); + spin_lock(&netlbl_domhsh_lock); if (entry->domain != NULL) { bkt = netlbl_domhsh_hash(entry->domain); - spin_lock(&netlbl_domhsh_lock); if (netlbl_domhsh_search(entry->domain) == NULL) list_add_tail_rcu(&entry->list, &rcu_dereference(netlbl_domhsh)->tbl[bkt]); else ret_val = -EEXIST; - spin_unlock(&netlbl_domhsh_lock); } else { INIT_LIST_HEAD(&entry->list); - spin_lock(&netlbl_domhsh_def_lock); if (rcu_dereference(netlbl_domhsh_def) == NULL) rcu_assign_pointer(netlbl_domhsh_def, entry); else ret_val = -EEXIST; - spin_unlock(&netlbl_domhsh_def_lock); } + spin_unlock(&netlbl_domhsh_lock); audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info); if (audit_buf != NULL) { audit_log_format(audit_buf, @@ -337,23 +332,16 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) entry->domain); break; } - if (entry != rcu_dereference(netlbl_domhsh_def)) { - spin_lock(&netlbl_domhsh_lock); - if (entry->valid) { - entry->valid = 0; + spin_lock(&netlbl_domhsh_lock); + if (entry->valid) { + entry->valid = 0; + if (entry != rcu_dereference(netlbl_domhsh_def)) list_del_rcu(&entry->list); - ret_val = 0; - } - spin_unlock(&netlbl_domhsh_lock); - } else { - spin_lock(&netlbl_domhsh_def_lock); - if (entry->valid) { - entry->valid = 0; + else rcu_assign_pointer(netlbl_domhsh_def, NULL); - ret_val = 0; - } - spin_unlock(&netlbl_domhsh_def_lock); + ret_val = 0; } + spin_unlock(&netlbl_domhsh_lock); audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_DEL, audit_info); if (audit_buf != NULL) { - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v8 16/18] NetLabel: Introduce static network labels for unlabeled connections
Most trusted OSs, with the exception of Linux, have the ability to specify static security labels for unlabeled networks. This patch adds this ability to the NetLabel packet labeling framework. If the NetLabel subsystem is called to determine the security attributes of an incoming packet it first checks to see if any recognized NetLabel packet labeling protocols are in-use on the packet. If none can be found then the unlabled connection table is queried and based on the packets incoming interface and address it is matched with a security label as configured by the administrator using the netlabel_tools package. The matching security label is returned to the caller just as if the packet was explicitly labeled using a labeling protocol. --- include/net/netlabel.h|6 net/netlabel/netlabel_kapi.c | 16 net/netlabel/netlabel_unlabeled.c | 1367 + net/netlabel/netlabel_unlabeled.h | 145 4 files changed, 1516 insertions(+), 18 deletions(-) diff --git a/include/net/netlabel.h b/include/net/netlabel.h index a3bffb4..b3213c7 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -67,7 +67,11 @@ * NetLabel NETLINK protocol */ -#define NETLBL_PROTO_VERSION1 +/* NetLabel NETLINK protocol version + * 1: initial version + * 2: added static labels for unlabeled connections + */ +#define NETLBL_PROTO_VERSION2 /* NetLabel NETLINK types/families */ #define NETLBL_NLTYPE_NONE 0 diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 4914615..c69e3e1 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -312,7 +312,7 @@ socket_setattr_return: * @secattr: the security attributes * * Description: - * Examines the given sock to see any NetLabel style labeling has been + * Examines the given sock to see if any NetLabel style labeling has been * applied to the sock, if so it parses the socket label and returns the * security attributes in @secattr. Returns zero on success, negative values * on failure. @@ -320,13 +320,7 @@ socket_setattr_return: */ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) { - int ret_val; - - ret_val = cipso_v4_sock_getattr(sk, secattr); - if (ret_val == 0) - return 0; - - return netlbl_unlabel_getattr(secattr); + return cipso_v4_sock_getattr(sk, secattr); } /** @@ -350,7 +344,7 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb, cipso_v4_skbuff_getattr(skb, secattr) == 0) return 0; - return netlbl_unlabel_getattr(secattr); + return netlbl_unlabel_getattr(skb, family, secattr); } /** @@ -434,6 +428,10 @@ static int __init netlbl_init(void) if (ret_val != 0) goto init_failure; + ret_val = netlbl_unlabel_init(NETLBL_UNLHSH_BITSIZE); + if (ret_val != 0) + goto init_failure; + ret_val = netlbl_netlink_init(); if (ret_val != 0) goto init_failure; diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 5e11394..d289ff4 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -10,7 +10,7 @@ */ /* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 + * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - 2007 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,22 +36,93 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include #include #include - +#include +#include +#include #include #include +#include #include "netlabel_user.h" #include "netlabel_domainhash.h" #include "netlabel_unlabeled.h" +#include "netlabel_mgmt.h" + +/* NOTE: at present we always use init's network namespace since we don't + * presently support different namespaces even though the majority of + * the functions in this file are "namespace safe" */ + +/* The unlabeled connection hash table which we use to map network interfaces + * and addresses of unlabeled packets to a user specified secid value for the + * LSM. The hash table is used to lookup the network interface entry + * (struct netlbl_unlhsh_iface) and then the interface entry is used to + * lookup an IP address match from an ordered list. If a network interface + * match can not be found in the hash table then the default entry + * (netlbl_unlhsh_def) is used. The IP address entry list + * (struct netlbl_unlhsh_addr) is ordered such that the entries with a + * larger netmask come first. + */ +struct netlbl_unlhsh_tbl { + struct list_head *tbl; + u32 size; +}; +struct netlbl_unlhsh_addr4 { + __be32 addr; + __be32 mask; + u32 secid; + + u32 valid; +
[RFC PATCH v8 11/18] SELinux: Add a capabilities bitmap to SELinux policy version 22
Add a new policy capabilities bitmap to SELinux policy version 22. This bitmap will enable the security server to query the policy to determine which features it supports. --- security/selinux/Kconfig|2 - security/selinux/include/security.h | 15 ++ security/selinux/selinuxfs.c| 89 +-- security/selinux/ss/policydb.c | 18 +++ security/selinux/ss/policydb.h |2 + security/selinux/ss/services.c | 67 ++ 6 files changed, 185 insertions(+), 8 deletions(-) diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index b32a459..2b517d6 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig @@ -145,7 +145,7 @@ config SECURITY_SELINUX_POLICYDB_VERSION_MAX config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE int "NSA SELinux maximum supported policy format version value" depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX - range 15 21 + range 15 22 default 19 help This option sets the value for the maximum policy format version diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index a33437b..a22de97 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -25,13 +25,14 @@ #define POLICYDB_VERSION_MLS 19 #define POLICYDB_VERSION_AVTAB 20 #define POLICYDB_VERSION_RANGETRANS21 +#define POLICYDB_VERSION_POLCAP22 /* Range of policy versions we understand*/ #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE #else -#define POLICYDB_VERSION_MAX POLICYDB_VERSION_RANGETRANS +#define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP #endif struct netlbl_lsm_secattr; @@ -39,8 +40,19 @@ struct netlbl_lsm_secattr; extern int selinux_enabled; extern int selinux_mls_enabled; +/* Policy capabilities */ +enum { + POLICYDB_CAPABILITY_NETPEER, + __POLICYDB_CAPABILITY_MAX +}; +#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1) + +extern int selinux_policycap_netpeer; + int security_load_policy(void * data, size_t len); +int security_policycap_supported(unsigned int req_cap); + #define SEL_VEC_MAX 32 struct av_decision { u32 allowed; @@ -91,6 +103,7 @@ int security_get_classes(char ***classes, int *nclasses); int security_get_permissions(char *class, char ***perms, int *nperms); int security_get_reject_unknown(void); int security_get_allow_unknown(void); +int security_get_policycaps(int *len, int **values); #define SECURITY_FS_USE_XATTR 1 /* use xattr */ #define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */ diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 2fa483f..b87e9eb 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -2,6 +2,11 @@ * * Added conditional policy language extensions * + * Updated: Hewlett-Packard <[EMAIL PROTECTED]> + * + * Added support for the policy capability bitmap + * + * Copyright (C) 2007 Hewlett-Packard Development Company, L.P. * Copyright (C) 2003 - 2004 Tresys Technology, LLC * Copyright (C) 2004 Red Hat, Inc., James Morris <[EMAIL PROTECTED]> * This program is free software; you can redistribute it and/or modify @@ -35,6 +40,11 @@ #include "objsec.h" #include "conditional.h" +/* Policy capability filenames */ +static char *policycap_names[] = { + "network_peer_controls" +}; + unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; #ifdef CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT @@ -72,6 +82,9 @@ static int *bool_pending_values = NULL; static struct dentry *class_dir = NULL; static unsigned long last_class_ino; +/* global data for policy capabilities */ +static struct dentry *policycap_dir = NULL; + extern void selnl_notify_setenforce(int val); /* Check whether a task is allowed to use a security operation. */ @@ -111,10 +124,11 @@ enum sel_inos { static unsigned long sel_last_ino = SEL_INO_NEXT - 1; -#define SEL_INITCON_INO_OFFSET 0x0100 -#define SEL_BOOL_INO_OFFSET0x0200 -#define SEL_CLASS_INO_OFFSET 0x0400 -#define SEL_INO_MASK 0x00ff +#define SEL_INITCON_INO_OFFSET 0x0100 +#define SEL_BOOL_INO_OFFSET0x0200 +#define SEL_CLASS_INO_OFFSET 0x0400 +#define SEL_POLICYCAP_INO_OFFSET 0x0800 +#define SEL_INO_MASK 0x00ff #define TMPBUFLEN 12 static ssize_t sel_read_enforce(struct file *filp, char __user *buf, @@ -263,6 +277,7 @@ static const struct file_operations sel_policyvers_ops = { /* declaration for sel_write_load */ static int sel_make_bools(void); static int sel_make_classes(void); +static int sel_make_po
[RFC PATCH v8 08/18] SELinux: Convert the netif code to use ifindex values
The current SELinux netif code requires the caller have a valid net_device struct pointer to lookup network interface information. However, we don't always have a valid net_device pointer so convert the netif code to use the ifindex values we always have as part of the sk_buff. This patch also removes the default message SID from the network interface record, it is not being used and therefore is "dead code". --- security/selinux/hooks.c|4 - security/selinux/include/netif.h|4 - security/selinux/include/objsec.h |5 - security/selinux/include/security.h |3 security/selinux/netif.c| 254 --- security/selinux/ss/services.c | 10 - 6 files changed, 155 insertions(+), 125 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 2188b9c..2ca8dfb 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3616,7 +3616,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, if (!skb->dev) goto out; - err = sel_netif_sids(skb->dev, &if_sid, NULL); + err = sel_netif_sid(skb->iif, &if_sid); if (err) goto out; @@ -3942,7 +3942,7 @@ static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device * isec = inode->i_security; - err = sel_netif_sids(dev, &if_sid, NULL); + err = sel_netif_sid(dev->ifindex, &if_sid); if (err) goto out; diff --git a/security/selinux/include/netif.h b/security/selinux/include/netif.h index 8bd6f99..ce23edd 100644 --- a/security/selinux/include/netif.h +++ b/security/selinux/include/netif.h @@ -7,6 +7,8 @@ * Author: James Morris <[EMAIL PROTECTED]> * * Copyright (C) 2003 Red Hat, Inc., James Morris <[EMAIL PROTECTED]> + * Copyright (C) 2007 Hewlett-Packard Development Company, L.P. + *Paul Moore, <[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, @@ -15,7 +17,7 @@ #ifndef _SELINUX_NETIF_H_ #define _SELINUX_NETIF_H_ -int sel_netif_sids(struct net_device *dev, u32 *if_sid, u32 *msg_sid); +int sel_netif_sid(int ifindex, u32 *sid); #endif /* _SELINUX_NETIF_H_ */ diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 642a9fd..e41a2aa 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -95,9 +95,8 @@ struct bprm_security_struct { }; struct netif_security_struct { - struct net_device *dev; /* back pointer */ - u32 if_sid; /* SID for this interface */ - u32 msg_sid;/* default SID for messages received on this interface */ + int ifindex;/* device index */ + u32 sid;/* SID for this interface */ }; struct sk_security_struct { diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 39337af..a33437b 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -77,8 +77,7 @@ int security_get_user_sids(u32 callsid, char *username, int security_port_sid(u16 domain, u16 type, u8 protocol, u16 port, u32 *out_sid); -int security_netif_sid(char *name, u32 *if_sid, - u32 *msg_sid); +int security_netif_sid(char *name, u32 *if_sid); int security_node_sid(u16 domain, void *addr, u32 addrlen, u32 *out_sid); diff --git a/security/selinux/netif.c b/security/selinux/netif.c index e87ab94..ee49a73 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c @@ -7,6 +7,8 @@ * Author: James Morris <[EMAIL PROTECTED]> * * Copyright (C) 2003 Red Hat, Inc., James Morris <[EMAIL PROTECTED]> + * Copyright (C) 2007 Hewlett-Packard Development Company, L.P. + *Paul Moore <[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, @@ -29,14 +31,6 @@ #define SEL_NETIF_HASH_SIZE64 #define SEL_NETIF_HASH_MAX 1024 -#undef DEBUG - -#ifdef DEBUG -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - struct sel_netif { struct list_head list; @@ -49,174 +43,217 @@ static LIST_HEAD(sel_netif_list); static DEFINE_SPINLOCK(sel_netif_lock); static struct list_head sel_netif_hash[SEL_NETIF_HASH_SIZE]; -static inline u32 sel_netif_hasfn(struct net_device *dev) +/** + * sel_netif_hashfn - Hashing function for the interface table + * @ifindex: the network interface + * + * Description: + * This is the hashing function for the network interface table, it returns the + * bucket number for the given interface. + * + */ +static inline u32 sel_ne
[RFC PATCH v8 13/18] SELinux: Better integration between peer labeling subsystems
Rework the handling of network peer labels so that the different peer labeling subsystems work better together. This includes moving both subsystems to a single "peer" object class which involves not only changes to the permission checks but an improved method of consolidating multiple packet peer labels. As part of this work the inbound packet permission check code has been heavily modified to handle both the old and new behavior in as sane a fashion as possible. --- security/selinux/hooks.c| 204 +++ security/selinux/include/netlabel.h |3 + security/selinux/include/objsec.h |2 security/selinux/include/security.h |4 + security/selinux/netlabel.c | 10 +- security/selinux/ss/services.c | 85 +++ 6 files changed, 208 insertions(+), 100 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 05b58cc..e088a31 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -50,6 +50,7 @@ #include #include /* for local_port_range[] */ #include/* struct or_callable used in sock_rcv_skb */ +#include #include #include #include @@ -3189,36 +3190,39 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, } /** - * selinux_skb_extlbl_sid - Determine the external label of a packet + * selinux_skb_peerlbl_sid - Determine the peer label of a packet * @skb: the packet * @family: protocol family - * @sid: the packet's SID + * @sid: the packet's peer label SID * * Description: - * Check the various different forms of external packet labeling and determine - * the external SID for the packet. If only one form of external labeling is - * present then it is used, if both labeled IPsec and NetLabel labels are - * present then the SELinux type information is taken from the labeled IPsec - * SA and the MLS sensitivity label information is taken from the NetLabel - * security attributes. This bit of "magic" is done in the call to - * selinux_netlbl_skbuff_getsid(). + * Check the various different forms of network peer labeling and determine + * the peer label/SID for the packet; most of the magic actually occurs in + * the security server function security_net_peersid_cmp(). The function + * returns zero if the value in @sid is valid (although it may be SECSID_NULL) + * or -EACCES if @sid is invalid due to inconsistencies with the different + * peer labels. * */ -static void selinux_skb_extlbl_sid(struct sk_buff *skb, - u16 family, - u32 *sid) +static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) { u32 xfrm_sid; u32 nlbl_sid; + u32 nlbl_type; selinux_skb_xfrm_sid(skb, &xfrm_sid); - if (selinux_netlbl_skbuff_getsid(skb, -family, -(xfrm_sid == SECSID_NULL ? - SECINITSID_NETMSG : xfrm_sid), -&nlbl_sid) != 0) - nlbl_sid = SECSID_NULL; - *sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid); + selinux_netlbl_skbuff_getsid(skb, +family, +SECINITSID_NETMSG, +&nlbl_type, +&nlbl_sid); + + if (security_net_peersid_resolve(nlbl_sid, nlbl_type, +xfrm_sid, +sid) != 0) + return -EACCES; + + return 0; } /* socket security operations */ @@ -3284,6 +3288,7 @@ static int selinux_socket_post_create(struct socket *sock, int family, if (sock->sk) { sksec = sock->sk->sk_security; sksec->sid = isec->sid; + sksec->sclass = isec->sclass; err = selinux_netlbl_socket_post_create(sock); } @@ -3587,104 +3592,114 @@ static int selinux_socket_unix_may_send(struct socket *sock, return 0; } -static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, - struct avc_audit_data *ad, - u16 family, char *addrp) +static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk, + struct sk_buff *skb, + struct avc_audit_data *ad, + u16 family, + char *addrp) { - int err = 0; - u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0; - struct socket *sock; - u16 sock_class = 0; - u32 sock_sid = 0; - - read_lock_bh(&sk->sk_callback_lock); - sock = sk->sk_socket; - if (sock) { - st
[RFC PATCH v8 10/18] SELinux: Add a network node caching mechanism similar to the sel_netif_*() functions
-3922,9 +3921,11 @@ out: #ifdef CONFIG_NETFILTER -static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *dev, +static int selinux_ip_postroute_last_compat(struct sock *sk, + struct net_device *dev, struct avc_audit_data *ad, - u16 family, char *addrp, int len) + u16 family, + char *addrp) { int err = 0; u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0; @@ -3975,7 +3976,7 @@ static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device * if (err) goto out; - err = security_node_sid(family, addrp, len, &node_sid); + err = sel_netnode_sid(addrp, family, &node_sid); if (err) goto out; @@ -4009,7 +4010,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum, u16 family) { char *addrp; - int len, err = 0; + int err = 0; struct sock *sk; struct avc_audit_data ad; struct net_device *dev = (struct net_device *)out; @@ -4026,13 +4027,13 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum, ad.u.net.netif = dev->ifindex; ad.u.net.family = family; - err = selinux_parse_skb(skb, &ad, &addrp, &len, 0, &proto); + err = selinux_parse_skb(skb, &ad, &addrp, 0, &proto); if (err) goto out; if (selinux_compat_net) err = selinux_ip_postroute_last_compat(sk, dev, &ad, - family, addrp, len); + family, addrp); else err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET, PACKET__SEND, &ad); diff --git a/security/selinux/include/netnode.h b/security/selinux/include/netnode.h new file mode 100644 index 000..1b94450 --- /dev/null +++ b/security/selinux/include/netnode.h @@ -0,0 +1,32 @@ +/* + * Network node table + * + * SELinux must keep a mapping of network nodes to labels/SIDs. This + * mapping is maintained as part of the normal policy but a fast cache is + * needed to reduce the lookup overhead since most of these queries happen on + * a per-packet basis. + * + * Author: Paul Moore <[EMAIL PROTECTED]> + * + */ + +/* + * (c) Copyright Hewlett-Packard Development Company, L.P., 2007 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _SELINUX_NETNODE_H +#define _SELINUX_NETNODE_H + +int sel_netnode_sid(void *addr, u16 family, u32 *sid); + +#endif diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index e41a2aa..6140734 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -99,6 +99,15 @@ struct netif_security_struct { u32 sid;/* SID for this interface */ }; +struct netnode_security_struct { + union { + __be32 ipv4;/* IPv4 node address */ + struct in6_addr ipv6; /* IPv6 node address */ + } addr; + u32 sid;/* SID for this node */ + u16 family; /* address family */ +}; + struct sk_security_struct { struct sock *sk;/* back pointer to sk object */ u32 sid;/* SID of this object */ diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c new file mode 100644 index 000..0cd66b8 --- /dev/null +++ b/security/selinux/netnode.c @@ -0,0 +1,351 @@ +/* + * Network node table + * + * SELinux must keep a mapping of network nodes to labels/SIDs. This + * mapping is maintained as part of the normal policy but a fast cache is + * needed to reduce the lookup overhead since most of these queries happen on + * a per-packet basis. + * + * Author: Paul Moore <[EMAIL PROTECTED]> + * + * This code is heavily based on the "netif" concept originally developed by + * James Morris <[EMAIL PROTECTED]> + * (see security/selinux/netif.c for more information) + * + */ + +/* + * (c) Copyright Hewlett-Packard Development Company, L.P., 2007 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of ver
[RFC PATCH v8 00/18] Update to the labeled networking patches for 2.6.25
Another update to the labeled networking patchset, the lblnet-2.6_testing git tree on infradead.org has been updated too for those of you who prefer to get the changes that way. With this version of the patchset I'm now considering the patches "feature complete" for 2.6.25. However, the push to get the features done in time has meant that my testing has been, and continues to be, pretty light so please don't consider this patch ready for inclusion anywhere yet. I'm posting these changes for people to review and test. Since v7 there have been quite a few changes, although they have all been in support of the big change - packet ingress/egress controls (formerly know as "flow controls" to some SELinux folks). This should allow SELinux (and other LSMs) to provide packet level access control to all IP traffic entering and leaving the system. The two other big changes, the shift from skb->dev to skb->iif and the SELinux network node caching mechanism, are in support of these new controls although other aspects of the SELinux code benefit as well (check out the patches). Comments are always welcome and people willing to help test are even more welcome. I'll get some SELinux policy patches out next week to help enable the new functionality and if everything is still looking okay I'll ping Andew Morton to see if I can get the latest version of these patches included in the -mm tree (previous versions are already included). Thanks. -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v8 06/18] LSM: Add inet_sys_snd_skb() LSM hook
Add an inet_sys_snd_skb() LSM hook to allow the LSM to provide packet level access control for all outbound packets. Using the existing postroute_last netfilter hook turns out to be problematic as it is can be invoked multiple times for a single packet, e.g. individual IPsec transforms, adding unwanted overhead and complicating the security policy. --- include/linux/security.h | 11 +++ net/ipv4/ip_output.c |7 +++ net/ipv6/ip6_output.c|5 + security/dummy.c |8 +++- security/security.c |6 ++ 5 files changed, 36 insertions(+), 1 deletions(-) diff --git a/include/linux/security.h b/include/linux/security.h index db19c92..1b8d332 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -876,6 +876,10 @@ struct request_sock; * Sets the connection's peersid to the secmark on skb. * @req_classify_flow: * Sets the flow's sid to the openreq sid. + * @inet_sys_snd_skb: + * Check permissions on outgoing network packets. + * @skb is the packet to check + * @family is the packet's address family * * Security hooks for XFRM operations. * @@ -1416,6 +1420,7 @@ struct security_operations { void (*inet_csk_clone)(struct sock *newsk, const struct request_sock *req); void (*inet_conn_established)(struct sock *sk, struct sk_buff *skb); void (*req_classify_flow)(const struct request_sock *req, struct flowi *fl); + int (*inet_sys_snd_skb)(struct sk_buff *skb, int family); #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM @@ -2328,6 +2333,7 @@ void security_sk_free(struct sock *sk); void security_sk_clone(const struct sock *sk, struct sock *newsk); void security_sk_classify_flow(struct sock *sk, struct flowi *fl); void security_req_classify_flow(const struct request_sock *req, struct flowi *fl); +int security_inet_sys_snd_skb(struct sk_buff *skb, int family); void security_sock_graft(struct sock*sk, struct socket *parent); int security_inet_conn_request(struct sock *sk, struct sk_buff *skb, struct request_sock *req); @@ -2471,6 +2477,11 @@ static inline void security_req_classify_flow(const struct request_sock *req, st { } +static inline int security_inet_sys_snd_skb(struct sk_buff *skb, int family) +{ + return 0; +} + static inline void security_sock_graft(struct sock* sk, struct socket *parent) { } diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index fd99fbd..82a7297 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -204,6 +204,8 @@ static inline int ip_skb_dst_mtu(struct sk_buff *skb) static int ip_finish_output(struct sk_buff *skb) { + int err; + #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) /* Policy lookup after SNAT yielded a new policy */ if (skb->dst->xfrm != NULL) { @@ -211,6 +213,11 @@ static int ip_finish_output(struct sk_buff *skb) return dst_output(skb); } #endif + + err = security_inet_sys_snd_skb(skb, AF_INET); + if (err) + return err; + if (skb->len > ip_skb_dst_mtu(skb) && !skb_is_gso(skb)) return ip_fragment(skb, ip_finish_output2); else diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 6338a9c..44ddf32 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -72,8 +72,13 @@ static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *f static int ip6_output_finish(struct sk_buff *skb) { + int err; struct dst_entry *dst = skb->dst; + err = security_inet_sys_snd_skb(skb, AF_INET6); + if (err) + return err; + if (dst->hh) return neigh_hh_output(dst->hh, skb); else if (dst->neighbour) diff --git a/security/dummy.c b/security/dummy.c index 0b62f95..384979a 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -848,6 +848,11 @@ static inline void dummy_req_classify_flow(const struct request_sock *req, struct flowi *fl) { } + +static inline int dummy_inet_sys_snd_skb(struct sk_buff *skb, int family) +{ + return 0; +} #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM @@ -1122,7 +1127,8 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, inet_csk_clone); set_to_dummy_if_null(ops, inet_conn_established); set_to_dummy_if_null(ops, req_classify_flow); - #endif/* CONFIG_SECURITY_NETWORK */ + set_to_dummy_if_null(ops, inet_sys_snd_skb); +#endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM set_to_dummy_if_null(ops, xfrm_policy_alloc_security); set_to_dummy_if_null(ops, xfrm_policy_clone_security); diff --git a/security/security.c b/security/security.c index 3bdcada..7f55459 100644 --- a/security/security.c +++ b/security/security.c @@ -961,6 +961,12 @@ void security_req_classify_
[RFC PATCH v8 07/18] NetLabel: Add IP address family information to the netlbl_skbuff_getattr() function
In order to do any sort of IP header inspection of incoming packets we need to know which address family, AF_INET/AF_INET6/etc., it belongs to and since the sk_buff structure does not store this information we need to pass along the address family separate from the packet itself. --- include/net/netlabel.h |2 ++ net/netlabel/netlabel_kapi.c|2 ++ security/selinux/hooks.c| 24 ++-- security/selinux/include/netlabel.h |8 +++- security/selinux/netlabel.c | 12 +--- 5 files changed, 38 insertions(+), 10 deletions(-) diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 18b73cf..a3bffb4 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -363,6 +363,7 @@ int netlbl_sock_setattr(struct sock *sk, int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr); int netlbl_skbuff_getattr(const struct sk_buff *skb, + u16 family, struct netlbl_lsm_secattr *secattr); void netlbl_skbuff_err(struct sk_buff *skb, int error); @@ -415,6 +416,7 @@ static inline int netlbl_sock_getattr(struct sock *sk, return -ENOSYS; } static inline int netlbl_skbuff_getattr(const struct sk_buff *skb, + u16 family, struct netlbl_lsm_secattr *secattr) { return -ENOSYS; diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index d3762ea..4914615 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -332,6 +332,7 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) /** * netlbl_skbuff_getattr - Determine the security attributes of a packet * @skb: the packet + * @family: protocol family * @secattr: the security attributes * * Description: @@ -342,6 +343,7 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) * */ int netlbl_skbuff_getattr(const struct sk_buff *skb, + u16 family, struct netlbl_lsm_secattr *secattr) { if (CIPSO_V4_OPTEXIST(skb) && diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8bb673b..2188b9c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3192,6 +3192,7 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, /** * selinux_skb_extlbl_sid - Determine the external label of a packet * @skb: the packet + * @family: protocol family * @sid: the packet's SID * * Description: @@ -3204,13 +3205,16 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, * selinux_netlbl_skbuff_getsid(). * */ -static void selinux_skb_extlbl_sid(struct sk_buff *skb, u32 *sid) +static void selinux_skb_extlbl_sid(struct sk_buff *skb, + u16 family, + u32 *sid) { u32 xfrm_sid; u32 nlbl_sid; selinux_skb_xfrm_sid(skb, &xfrm_sid); if (selinux_netlbl_skbuff_getsid(skb, +family, (xfrm_sid == SECSID_NULL ? SECINITSID_NETMSG : xfrm_sid), &nlbl_sid) != 0) @@ -3703,7 +3707,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) if (err) goto out; - err = selinux_netlbl_sock_rcv_skb(sksec, skb, &ad); + err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad); if (err) goto out; @@ -3760,11 +3764,19 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff * { u32 peer_secid = SECSID_NULL; int err = 0; + u16 family; + + if (sock) + family = sock->sk->sk_family; + else if (skb->sk) + family = skb->sk->sk_family; + else + family = PF_UNSPEC; - if (sock && sock->sk->sk_family == PF_UNIX) + if (sock && family == PF_UNIX) selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); else if (skb) - selinux_skb_extlbl_sid(skb, &peer_secid); + selinux_skb_extlbl_sid(skb, family, &peer_secid); if (peer_secid == SECSID_NULL) err = -EINVAL; @@ -3825,7 +3837,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, u32 newsid; u32 peersid; - selinux_skb_extlbl_sid(skb, &peersid); + selinux_skb_extlbl_sid(skb, sk->sk_family, &peersid); if (peersid == SECSID_NULL) { req->secid = sksec->sid; req->peer_secid = SECSID_NULL; @@ -3863,7 +3875,7 @@ static void selinux_inet_conn_established(struct sock *sk, { struct sk_security_struct *sksec = sk->sk_security;
[RFC PATCH v8 14/18] SELinux: Enable dynamic enable/disable of the network access checks
This patch introduces a mechanism for checking when labeled IPsec or SECMARK are in use by keeping introducing a configuration reference counter for each subsystem. In the case of labeled IPsec, whenever a labeled SA or SPD entry is created the labeled IPsec/XFRM reference count is increased and when the entry is removed it is decreased. In the case of SECMARK, when a SECMARK target is created the reference count is increased and later decreased when the target is removed. These reference counters allow SELinux to quickly determine if either of these subsystems are enabled. NetLabel already has a similar mechanism which provides the netlbl_enabled() function. This patch also renames the selinux_relabel_packet_permission() function to selinux_secmark_relabel_packet_permission() as the original name and description were misleading in that they referenced a single packet label which is not the case. --- include/linux/selinux.h | 45 +++--- net/netfilter/xt_SECMARK.c | 13 ++- security/selinux/exports.c | 20 +++-- security/selinux/hooks.c| 46 +++ security/selinux/include/xfrm.h | 12 ++ security/selinux/xfrm.c | 18 ++- 6 files changed, 132 insertions(+), 22 deletions(-) diff --git a/include/linux/selinux.h b/include/linux/selinux.h index 6080f73..8c2cc4c 100644 --- a/include/linux/selinux.h +++ b/include/linux/selinux.h @@ -120,16 +120,35 @@ void selinux_get_task_sid(struct task_struct *tsk, u32 *sid); int selinux_string_to_sid(char *str, u32 *sid); /** - * selinux_relabel_packet_permission - check permission to relabel a packet - * @sid: ID value to be applied to network packet (via SECMARK, most likely) + * selinux_secmark_relabel_packet_permission - secmark permission check + * @sid: SECMARK ID value to be applied to network packet * - * Returns 0 if the current task is allowed to label packets with the - * supplied security ID. Note that it is implicit that the packet is always - * being relabeled from the default unlabled value, and that the access - * control decision is made in the AVC. + * Returns 0 if the current task is allowed to set the SECMARK label of + * packets with the supplied security ID. Note that it is implicit that + * the packet is always being relabeled from the default unlabeled value, + * and that the access control decision is made in the AVC. */ -int selinux_relabel_packet_permission(u32 sid); +int selinux_secmark_relabel_packet_permission(u32 sid); +/** + * selinux_secmark_refcount_inc - increments the secmark use counter + * + * SELinux keeps track of the current SECMARK targets in use so it knows + * when to apply SECMARK label access checks to network packets. This + * function incements this reference count to indicate that a new SECMARK + * target has been configured. + */ +void selinux_secmark_refcount_inc(void); + +/** + * selinux_secmark_refcount_dec - decrements the secmark use counter + * + * SELinux keeps track of the current SECMARK targets in use so it knows + * when to apply SECMARK label access checks to network packets. This + * function decements this reference count to indicate that one of the + * existing SECMARK targets has been removed/flushed. + */ +void selinux_secmark_refcount_dec(void); #else static inline int selinux_audit_rule_init(u32 field, u32 op, @@ -184,11 +203,21 @@ static inline int selinux_string_to_sid(const char *str, u32 *sid) return 0; } -static inline int selinux_relabel_packet_permission(u32 sid) +static inline int selinux_secmark_relabel_packet_permission(u32 sid) { return 0; } +static inline void selinux_secmark_refcount_inc(void) +{ + return; +} + +static inline void selinux_secmark_refcount_dec(void) +{ + return; +} + #endif /* CONFIG_SECURITY_SELINUX */ #endif /* _LINUX_SELINUX_H */ diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c index 235806e..db4a1fe 100644 --- a/net/netfilter/xt_SECMARK.c +++ b/net/netfilter/xt_SECMARK.c @@ -72,12 +72,13 @@ static bool checkentry_selinux(struct xt_secmark_target_info *info) return false; } - err = selinux_relabel_packet_permission(sel->selsid); + err = selinux_secmark_relabel_packet_permission(sel->selsid); if (err) { printk(KERN_INFO PFX "unable to obtain relabeling permission\n"); return false; } + selinux_secmark_refcount_inc(); return true; } @@ -109,11 +110,20 @@ static bool checkentry(const char *tablename, const void *entry, return true; } +void destroy(const struct xt_target *target, void *targinfo) +{ + switch (mode) { + case SECMARK_MODE_SEL: + selinux_secmark_refcount_dec(); + } +} + static struct xt_target xt_s
Re: [RFC PATCH v8 18/18] SELinux: Add network ingress and egress control permission checks
On Friday 14 December 2007 4:51:29 pm Paul Moore wrote: > This patch implements packet ingress/egress controls for SELinux which > allow SELinux security policy to control the flow of all IPv4 and IPv6 > packets into and out of the system. Currently SELinux does not have proper > control over forwarded packets and this patch corrects this problem. > > Special thanks to Venkat Yekkirala <[EMAIL PROTECTED]> whose earlier > work on this topic eventually led to this patch. I've been thinking about this over the weekend and realized a few things ... {snip} > +static int selinux_inet_sys_snd_skb(struct sk_buff *skb, int family) > +{ > + int err = 0; > + > + if (!selinux_policycap_netpeer) > + return 0; > + > + if (netlbl_enabled() || selinux_xfrm_enabled()) { > + u32 if_sid; > + u32 node_sid; > + u32 peer_sid; > + char *addrp; > + struct avc_audit_data ad; > + > + AVC_AUDIT_DATA_INIT(&ad, NET); > + ad.u.net.netif = skb->iif; > + ad.u.net.family = family; > + err = selinux_parse_skb(skb, &ad, &addrp, 0, NULL); > + if (err) > + return err; > + > + err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); > + if (err) > + return err; I realized I made a mistake here: we should check to see if the skb has a socket associated with it and if it does get the peer_sid from there instead. If there is no socket to be found then do what we are already going above. > + err = sel_netif_sid(skb->iif, &if_sid); > + if (err) > + return err; > + err = avc_has_perm(if_sid, peer_sid, > +SECCLASS_PEER, PEER__EGRESS, &ad); > + if (err) > + return err; > + > + err = sel_netnode_sid(addrp, family, &node_sid); > + if (err) > + return err; > + err = avc_has_perm(node_sid, peer_sid, > +SECCLASS_PEER, PEER__EGRESS, &ad); We should probably have different permissions for the interface and node cases. Take the example of an admin who is only interested in enforcing interface controls and not node controls. They would most likely write the following policy rule to nullify the node check ... allow unlabeled_t peer_t:peer egress; ... which would end up applying to both the interface and node checks because they use the same permission. I'm thinking we should split the permissions like this: allow netif_t peer_t:peer if_egress; allow netnode_t peer_t: peer node_egress; ... and do something similar for the ingress side. Thoughts? > + } > + > + return err; > +} -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v8 06/18] LSM: Add inet_sys_snd_skb() LSM hook
On Monday 17 December 2007 2:45:50 pm Stephen Smalley wrote: > On Fri, 2007-12-14 at 16:50 -0500, Paul Moore wrote: > > Add an inet_sys_snd_skb() LSM hook to allow the LSM to provide packet > > level access control for all outbound packets. Using the existing > > postroute_last netfilter hook turns out to be problematic as it is can be > > invoked multiple times for a single packet, e.g. individual IPsec > > transforms, adding unwanted overhead and complicating the security > > policy. > > None of the netfilter hooks works for this purpose? None that we have found, no. Although if you can prove me wrong I'd be very happy. The problem is that the existing netfilter hooks can get hit multiple times in the case of labeled IPsec which was decided to be a no-no. > Obviously this one needs to get seen on netdev. Yep. I just wanted to make sure we were all in agreement on what we wanted/needed before I tried to make our case to the netdev folks. -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v8 09/18] SELinux: Only store the network interface's ifindex
On Monday 17 December 2007 2:56:41 pm Stephen Smalley wrote: > On Fri, 2007-12-14 at 16:50 -0500, Paul Moore wrote: > > /* Initialize an AVC audit data structure. */ > > #define AVC_AUDIT_DATA_INIT(_d,_t) \ > > -{ memset((_d), 0, sizeof(struct avc_audit_data)); (_d)->type = > > AVC_AUDIT_DATA_##_t; } > > +{ memset((_d), 0, sizeof(struct > > avc_audit_data)); \ > > + (_d)->type = AVC_AUDIT_DATA_##_t; \ > > + if ((_d)->type == AVC_AUDIT_DATA_NET) \ > > + (_d)->u.net.netif = -1; } > > As a minor nit, at the same time you do this, turn this into a static > inline function please. Can do ... although when talking about this with some other people I'm not sure I need to use -1 as a sentinel value, zero should work. If that is the case I won't need to change this definition. -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v8 10/18] SELinux: Add a network node caching mechanism similar to the sel_netif_*() functions
On Monday 17 December 2007 3:35:28 pm Stephen Smalley wrote: > On Fri, 2007-12-14 at 16:50 -0500, Paul Moore wrote: > > This patch adds a SELinux IP address/node SID caching mechanism similar > > to the sel_netif_*() functions. The node SID queries in the SELinux > > hooks files are also modified to take advantage of this new > > functionality. In addition, remove the address length information from > > the sk_buff parsing routines as it is redundant since we already have the > > address family. > > This is very nice - we also need the same kind of cache for port SIDs. Thanks. Any problem if we wait until 2.6.26 for a port SID cache? It shouldn't be any worse than it is now (the new code is not concerned with ports) and the current patchset is already large enough that it keeps me up at night thinking about all the places it could go wrong ... -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v8 18/18] SELinux: Add network ingress and egress control permission checks
On Monday 17 December 2007 3:05:37 pm Stephen Smalley wrote: > On Sun, 2007-12-16 at 11:47 -0500, Paul Moore wrote: > > On Friday 14 December 2007 4:51:29 pm Paul Moore wrote: > > > This patch implements packet ingress/egress controls for SELinux which > > > allow SELinux security policy to control the flow of all IPv4 and IPv6 > > > packets into and out of the system. Currently SELinux does not have > > > proper control over forwarded packets and this patch corrects this > > > problem. > > > > > > Special thanks to Venkat Yekkirala <[EMAIL PROTECTED]> whose > > > earlier work on this topic eventually led to this patch. > > > > I've been thinking about this over the weekend and realized a few things > > ... > > > > {snip} > > > > > +static int selinux_inet_sys_snd_skb(struct sk_buff *skb, int family) > > > +{ > > > + int err = 0; > > > + > > > + if (!selinux_policycap_netpeer) > > > + return 0; > > > + > > > + if (netlbl_enabled() || selinux_xfrm_enabled()) { > > > + u32 if_sid; > > > + u32 node_sid; > > > + u32 peer_sid; > > > + char *addrp; > > > + struct avc_audit_data ad; > > > + > > > + AVC_AUDIT_DATA_INIT(&ad, NET); > > > + ad.u.net.netif = skb->iif; > > > + ad.u.net.family = family; > > > + err = selinux_parse_skb(skb, &ad, &addrp, 0, NULL); > > > + if (err) > > > + return err; > > > + > > > + err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); > > > + if (err) > > > + return err; > > > > I realized I made a mistake here: we should check to see if the skb has a > > socket associated with it and if it does get the peer_sid from there > > instead. If there is no socket to be found then do what we are already > > going above. > > In what case do you expect the two SIDs to diverge? The case of CIPSO immediately springs to mind. If you query the packet directly you will get a SID similar to what you see on incoming packets: the "netlabel_peer_t" type plus the CIPSO MLS sensitivity label. If you query the socket which originated the packet you'll get the original, native SELinux label/SID. In my mind using the socket's label is a shortcut to get the full/true/original/etc. label quickly. There is most likely also a performance advantage in pulling the SID from the socket. > What if we later provide an API to allow a sender to send a datagram > with a particular label rather than always requiring them to be the same > as the sending socket? Then we can transition from using a mix between socket and packet labels to just packet labels. I don't see any _significant_ barriers to that approach in the ingress/egress controls as proposed. If you do, let me know. > > > + err = sel_netif_sid(skb->iif, &if_sid); > > > + if (err) > > > + return err; > > > + err = avc_has_perm(if_sid, peer_sid, > > > +SECCLASS_PEER, PEER__EGRESS, &ad); > > > + if (err) > > > + return err; > > > + > > > + err = sel_netnode_sid(addrp, family, &node_sid); > > > + if (err) > > > + return err; > > > + err = avc_has_perm(node_sid, peer_sid, > > > +SECCLASS_PEER, PEER__EGRESS, &ad); > > > > We should probably have different permissions for the interface and node > > cases. Take the example of an admin who is only interested in enforcing > > interface controls and not node controls. They would most likely write > > the following policy rule to nullify the node check ... > > > > allow unlabeled_t peer_t:peer egress; > > > > ... which would end up applying to both the interface and node checks > > because they use the same permission. I'm thinking we should split the > > permissions like this: > > > > allow netif_t peer_t:peer if_egress; > > allow netnode_t peer_t: peer node_egress; > > > > ... and do something similar for the ingress side. Thoughts? > > That starts to sound a lot like using netif and node classes instead of > the peer class. > allow peer_t netif_t:netif egress; > allow peer_t netnode_t:node egress; I see you noticed that too :) I've been mulling this over and over in my head for some time and I'm not sure which is better. I'm leaning towards sticking with the peer object class just because it reinforces the decision to treat the packet as an object. Good or bad, that is how SELinux currently treats packets and I fear that using the packet's peer label as the subject here could get confusing. -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v8 10/18] SELinux: Add a network node caching mechanism similar to the sel_netif_*() functions
On Tuesday 18 December 2007 8:26:35 am Stephen Smalley wrote: > On Mon, 2007-12-17 at 15:56 -0500, Paul Moore wrote: > > On Monday 17 December 2007 3:35:28 pm Stephen Smalley wrote: > > > On Fri, 2007-12-14 at 16:50 -0500, Paul Moore wrote: > > > > This patch adds a SELinux IP address/node SID caching mechanism > > > > similar to the sel_netif_*() functions. The node SID queries in the > > > > SELinux hooks files are also modified to take advantage of this new > > > > functionality. In addition, remove the address length information > > > > from the sk_buff parsing routines as it is redundant since we already > > > > have the address family. > > > > > > This is very nice - we also need the same kind of cache for port SIDs. > > > > Thanks. Any problem if we wait until 2.6.26 for a port SID cache? It > > shouldn't be any worse than it is now (the new code is not concerned with > > ports) and the current patchset is already large enough that it keeps me > > up at night thinking about all the places it could go wrong ... > > Yes, that's fine - just a note to file away for the future. We'll still > want the cache eventually though since the name_bind and name_connect > checks are based on the port SIDs and will remain even when the compat > checks are obsoleted. All righty, since neither you or James are in a hurry for this I'll "file it away" for 2.6.26. Thanks. -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v8 05/18] LSM: Add secctx_to_secid() LSM hook
On Tuesday 18 December 2007 3:25:54 am James Morris wrote: > On Fri, 14 Dec 2007, Paul Moore wrote: > > Add a secctx_to_secid() LSM hook to go along with the existing > > secid_to_secctx() LSM hook. This patch also includes the SELinux > > implementation for this hook. > > Please sign off your patches (especially this one asap, so I can push it > upstream). The lack of a sign-off line is actually intentional at this point as I wanted to make sure they didn't go anywhere before they were ready. For instance, I've got the changes that were pointed out yesterday on-list as well as a handful of IPv6 changes from some IPv6 folks here at HP. Most of the new peer object class code paths haven't even been tested yet. I realize we can still get fixes/corrections in after -rc1 but I'd like to try and minimize that if I can. I've been operating under the assumption that I've most likely got until the end of next week before I need to post "final-ish" version of the patches, complete with a signed-off line. If that isn't the case and you need these bits sooner (or now) please let me know. -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v8 18/18] SELinux: Add network ingress and egress control permission checks
On Monday 17 December 2007 3:05:37 pm Stephen Smalley wrote: > On Sun, 2007-12-16 at 11:47 -0500, Paul Moore wrote: > > We should probably have different permissions for the interface and node > > cases. Take the example of an admin who is only interested in enforcing > > interface controls and not node controls. They would most likely write > > the following policy rule to nullify the node check ... > > > > allow unlabeled_t peer_t:peer egress; > > > > ... which would end up applying to both the interface and node checks > > because they use the same permission. I'm thinking we should split the > > permissions like this: > > > > allow netif_t peer_t:peer if_egress; > > allow netnode_t peer_t: peer node_egress; > > > > ... and do something similar for the ingress side. Thoughts? > > That starts to sound a lot like using netif and node classes instead of > the peer class. > allow peer_t netif_t:netif egress; > allow peer_t netnode_t:node egress; Thinking about this some more ... egress/ingress make sense from an interface point of view but they sound out of place from a node point of view. After all, you are not "egressing" to a node, to are "sending to" a node. The same thing applies in the opposite direction, you don't "ingress" from a node, you "receive from" a node. With that in mind I'm thinking of going with the following: allow netif_t peer_t:peer { ingress egress }; allow netnode_t peer_t:peer { recv_from send_to }; Thoughts? Should I just forget all this and use the peer label as a subject label? -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH v8 18/18] SELinux: Add network ingress and egress control permission checks
On Tuesday 18 December 2007 10:14:41 am Stephen Smalley wrote: > On Tue, 2007-12-18 at 08:59 -0500, Paul Moore wrote: > > Thoughts? Should I just forget all this and use the peer label as a > > subject label? > > I'm not certain what we gain by using the peer as the object and class > in these checks, and it seems to make their meaning less clear. It > should be noted that we already use process labels as both subjects > (when the actor) and objects (when the target/recipient of an action, as > in signal delivery or IPC), and that process labels "flow" to sockets > they create and socket labels "flow" to packets they send, and socket > labels likewise serve dual roles as subjects (Can this socket send/recv > this packet?) and objects (Can this process send/recv on this socket?). > > In the case of locally generated or destined traffic, we always have a > local socket that we can use as the subject of the check, which I think > is why we end up not using packet/peer as the subject generally - we > essentially have two subjects to choose from, and we favor the local > one. But in the forwarded case, the packet/peer is the only > subject/actor in view really. Yep, I think you are right and I'm just slow to realize it. As pointed out earlier in the discussion, the awkwardness of using the packet's peer label as an object should have clued me into the fact that this was a bad idea. So, my last question is what permissions do we want to use for the netif/node object classes? allow peer_t netif_t:netif { egress ingress }; allow peer_t netnode_t:node { sendto/send recvfrom/recv }; What I'd like to avoid if possible is the protocol specific permissions we currently have for the netif and node object classes; it requires extra work in the kernel, it doesn't work at all for the forwarding case, and I have my doubts about the usefulness of the distinction. I think the ingress/egress permissions still make sense when applied to the netif object class but it's a bit of a stretch when applied to the node object class. I personally like the sendto/recvfrom permissions but if that is too much of a violation from existing precedence I imagine send/recv would work. Thoughts? -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v9 13/18] SELinux: Better integration between peer labeling subsystems
Rework the handling of network peer labels so that the different peer labeling subsystems work better together. This includes moving both subsystems to a single "peer" object class which involves not only changes to the permission checks but an improved method of consolidating multiple packet peer labels. As part of this work the inbound packet permission check code has been heavily modified to handle both the old and new behavior in as sane a fashion as possible. Signed-off-by: Paul Moore <[EMAIL PROTECTED]> --- security/selinux/hooks.c| 204 +++ security/selinux/include/netlabel.h |3 + security/selinux/include/objsec.h |2 security/selinux/include/security.h |4 + security/selinux/netlabel.c | 10 +- security/selinux/ss/services.c | 85 +++ 6 files changed, 208 insertions(+), 100 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 4250642..c156f6c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -50,6 +50,7 @@ #include #include /* for local_port_range[] */ #include/* struct or_callable used in sock_rcv_skb */ +#include #include #include #include @@ -3189,36 +3190,39 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, } /** - * selinux_skb_extlbl_sid - Determine the external label of a packet + * selinux_skb_peerlbl_sid - Determine the peer label of a packet * @skb: the packet * @family: protocol family - * @sid: the packet's SID + * @sid: the packet's peer label SID * * Description: - * Check the various different forms of external packet labeling and determine - * the external SID for the packet. If only one form of external labeling is - * present then it is used, if both labeled IPsec and NetLabel labels are - * present then the SELinux type information is taken from the labeled IPsec - * SA and the MLS sensitivity label information is taken from the NetLabel - * security attributes. This bit of "magic" is done in the call to - * selinux_netlbl_skbuff_getsid(). + * Check the various different forms of network peer labeling and determine + * the peer label/SID for the packet; most of the magic actually occurs in + * the security server function security_net_peersid_cmp(). The function + * returns zero if the value in @sid is valid (although it may be SECSID_NULL) + * or -EACCES if @sid is invalid due to inconsistencies with the different + * peer labels. * */ -static void selinux_skb_extlbl_sid(struct sk_buff *skb, - u16 family, - u32 *sid) +static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) { u32 xfrm_sid; u32 nlbl_sid; + u32 nlbl_type; selinux_skb_xfrm_sid(skb, &xfrm_sid); - if (selinux_netlbl_skbuff_getsid(skb, -family, -(xfrm_sid == SECSID_NULL ? - SECINITSID_NETMSG : xfrm_sid), -&nlbl_sid) != 0) - nlbl_sid = SECSID_NULL; - *sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid); + selinux_netlbl_skbuff_getsid(skb, +family, +SECINITSID_NETMSG, +&nlbl_type, +&nlbl_sid); + + if (security_net_peersid_resolve(nlbl_sid, nlbl_type, +xfrm_sid, +sid) != 0) + return -EACCES; + + return 0; } /* socket security operations */ @@ -3284,6 +3288,7 @@ static int selinux_socket_post_create(struct socket *sock, int family, if (sock->sk) { sksec = sock->sk->sk_security; sksec->sid = isec->sid; + sksec->sclass = isec->sclass; err = selinux_netlbl_socket_post_create(sock); } @@ -3587,104 +3592,114 @@ static int selinux_socket_unix_may_send(struct socket *sock, return 0; } -static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, - struct avc_audit_data *ad, - u16 family, char *addrp) +static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk, + struct sk_buff *skb, + struct avc_audit_data *ad, + u16 family, + char *addrp) { - int err = 0; - u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0; - struct socket *sock; - u16 sock_class = 0; - u32 sock_
[RFC PATCH v9 10/18] SELinux: Add a network node caching mechanism similar to the sel_netif_*() functions
This patch adds a SELinux IP address/node SID caching mechanism similar to the sel_netif_*() functions. The node SID queries in the SELinux hooks files are also modified to take advantage of this new functionality. In addition, remove the address length information from the sk_buff parsing routines as it is redundant since we already have the address family. Signed-off-by: Paul Moore <[EMAIL PROTECTED]> --- security/selinux/Makefile |9 + security/selinux/hooks.c | 33 ++- security/selinux/include/netnode.h | 32 +++ security/selinux/include/objsec.h |9 + security/selinux/netnode.c | 350 5 files changed, 416 insertions(+), 17 deletions(-) diff --git a/security/selinux/Makefile b/security/selinux/Makefile index dc3502e..00afd85 100644 --- a/security/selinux/Makefile +++ b/security/selinux/Makefile @@ -4,7 +4,14 @@ obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/ -selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o exports.o +selinux-y := avc.o \ +hooks.o \ +selinuxfs.o \ +netlink.o \ +nlmsgtab.o \ +netif.o \ +netnode.o \ +exports.o selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index b451b4c..4250642 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -76,6 +76,7 @@ #include "avc.h" #include "objsec.h" #include "netif.h" +#include "netnode.h" #include "xfrm.h" #include "netlabel.h" @@ -3158,7 +3159,7 @@ out: #endif /* IPV6 */ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, -char **addrp, int *len, int src, u8 *proto) +char **addrp, int src, u8 *proto) { int ret = 0; @@ -3167,7 +3168,6 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, ret = selinux_parse_skb_ipv4(skb, ad, proto); if (ret || !addrp) break; - *len = 4; *addrp = (char *)(src ? &ad->u.net.v4info.saddr : &ad->u.net.v4info.daddr); break; @@ -3177,7 +3177,6 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, ret = selinux_parse_skb_ipv6(skb, ad, proto); if (ret || !addrp) break; - *len = 16; *addrp = (char *)(src ? &ad->u.net.v6info.saddr : &ad->u.net.v6info.daddr); break; @@ -3377,7 +3376,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in break; } - err = security_node_sid(family, addrp, addrlen, &sid); + err = sel_netnode_sid(addrp, family, &sid); if (err) goto out; @@ -3589,7 +3588,8 @@ static int selinux_socket_unix_may_send(struct socket *sock, } static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, - struct avc_audit_data *ad, u16 family, char *addrp, int len) + struct avc_audit_data *ad, + u16 family, char *addrp) { int err = 0; u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0; @@ -3649,7 +3649,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, if (err) goto out; - err = security_node_sid(family, addrp, len, &node_sid); + err = sel_netnode_sid(addrp, family, &node_sid); if (err) goto out; @@ -3678,7 +3678,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) { u16 family; char *addrp; - int len, err = 0; + int err = 0; struct avc_audit_data ad; struct sk_security_struct *sksec = sk->sk_security; @@ -3694,13 +3694,12 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) ad.u.net.netif = skb->iif; ad.u.net.family = family; - err = selinux_parse_skb(skb, &ad, &addrp, &len, 1, NULL); + err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); if (err) goto out; if (selinux_compat_net) - err = selinux_sock_rcv_skb_compat(sk, skb, &ad, family, - addrp, len); + err = selinux_sock_rcv_skb_compat(sk, skb, &ad, family, addrp); else err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET,
[RFC PATCH v9 18/18] SELinux: Add network ingress and egress control permission checks
This patch implements packet ingress/egress controls for SELinux which allow SELinux security policy to control the flow of all IPv4 and IPv6 packets into and out of the system. Currently SELinux does not have proper control over forwarded packets and this patch corrects this problem. Special thanks to Venkat Yekkirala <[EMAIL PROTECTED]> whose earlier work on this topic eventually led to this patch. Signed-off-by: Paul Moore <[EMAIL PROTECTED]> --- security/selinux/hooks.c | 347 -- 1 files changed, 240 insertions(+), 107 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index d16f586..474ffe8 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -12,8 +12,8 @@ * Copyright (C) 2003 Red Hat, Inc., James Morris <[EMAIL PROTECTED]> * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * <[EMAIL PROTECTED]> - * Copyright (C) 2006 Hewlett-Packard Development Company, L.P. - * Paul Moore, <[EMAIL PROTECTED]> + * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. + * Paul Moore <[EMAIL PROTECTED]> * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd. * Yuichi Nakamura <[EMAIL PROTECTED]> * @@ -3608,6 +3608,83 @@ static int selinux_socket_unix_may_send(struct socket *sock, return 0; } +static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, + u32 peer_sid, + struct avc_audit_data *ad) +{ + int err; + u32 if_sid; + u32 node_sid; + + err = sel_netif_sid(ifindex, &if_sid); + if (err) + return err; + err = avc_has_perm(peer_sid, if_sid, + SECCLASS_NETIF, NETIF__INGRESS, ad); + if (err) + return err; + + err = sel_netnode_sid(addrp, family, &node_sid); + if (err) + return err; + return avc_has_perm(peer_sid, node_sid, + SECCLASS_NODE, NODE__RECVFROM, ad); +} + +static int selinux_inet_sys_snd_skb(struct sk_buff *skb, int family) +{ + int err = 0; + + if (!selinux_policycap_netpeer) + return 0; + + if (netlbl_enabled() || selinux_xfrm_enabled()) { + u32 if_sid; + u32 node_sid; + u32 peer_sid; + int ifindex = skb->dev->ifindex; + char *addrp; + struct sock *sk = skb->sk; + struct avc_audit_data ad; + + AVC_AUDIT_DATA_INIT(&ad, NET); + ad.u.net.netif = ifindex; + ad.u.net.family = family; + err = selinux_parse_skb(skb, &ad, &addrp, 0, NULL); + if (err) + return err; + + if (sk) { + /* packet was locally generated, get the peer label +* from the originating socket */ + struct sk_security_struct *sksec = sk->sk_security; + peer_sid = sksec->sid; + } else { + /* packet was generated by another host, get the peer +* label directly from the packet */ + err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); + if (err) + return err; + } + + err = sel_netif_sid(ifindex, &if_sid); + if (err) + return err; + err = avc_has_perm(peer_sid, if_sid, + SECCLASS_NETIF, NETIF__EGRESS, &ad); + if (err) + return err; + + err = sel_netnode_sid(addrp, family, &node_sid); + if (err) + return err; + err = avc_has_perm(peer_sid, node_sid, + SECCLASS_NODE, NODE__SENDTO, &ad); + } + + return err; +} + static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk, struct sk_buff *skb, struct avc_audit_data *ad, @@ -3748,6 +3825,10 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); if (err) return err; + err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family, + peer_sid, &ad); + if (err) + return err; err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, PEER__RECV, &ad); } @@ -3964
[RFC PATCH v9 08/18] SELinux: Convert the netif code to use ifindex values
The current SELinux netif code requires the caller have a valid net_device struct pointer to lookup network interface information. However, we don't always have a valid net_device pointer so convert the netif code to use the ifindex values we always have as part of the sk_buff. This patch also removes the default message SID from the network interface record, it is not being used and therefore is "dead code". Signed-off-by: Paul Moore <[EMAIL PROTECTED]> --- security/selinux/hooks.c|4 - security/selinux/include/netif.h|4 - security/selinux/include/objsec.h |5 - security/selinux/include/security.h |3 security/selinux/netif.c| 254 --- security/selinux/ss/services.c | 10 - 6 files changed, 155 insertions(+), 125 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 7b99d52..8336c93 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3616,7 +3616,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, if (!skb->dev) goto out; - err = sel_netif_sids(skb->dev, &if_sid, NULL); + err = sel_netif_sid(skb->iif, &if_sid); if (err) goto out; @@ -3941,7 +3941,7 @@ static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device * isec = inode->i_security; - err = sel_netif_sids(dev, &if_sid, NULL); + err = sel_netif_sid(dev->ifindex, &if_sid); if (err) goto out; diff --git a/security/selinux/include/netif.h b/security/selinux/include/netif.h index 8bd6f99..ce23edd 100644 --- a/security/selinux/include/netif.h +++ b/security/selinux/include/netif.h @@ -7,6 +7,8 @@ * Author: James Morris <[EMAIL PROTECTED]> * * Copyright (C) 2003 Red Hat, Inc., James Morris <[EMAIL PROTECTED]> + * Copyright (C) 2007 Hewlett-Packard Development Company, L.P. + *Paul Moore, <[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, @@ -15,7 +17,7 @@ #ifndef _SELINUX_NETIF_H_ #define _SELINUX_NETIF_H_ -int sel_netif_sids(struct net_device *dev, u32 *if_sid, u32 *msg_sid); +int sel_netif_sid(int ifindex, u32 *sid); #endif /* _SELINUX_NETIF_H_ */ diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 642a9fd..e41a2aa 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -95,9 +95,8 @@ struct bprm_security_struct { }; struct netif_security_struct { - struct net_device *dev; /* back pointer */ - u32 if_sid; /* SID for this interface */ - u32 msg_sid;/* default SID for messages received on this interface */ + int ifindex;/* device index */ + u32 sid;/* SID for this interface */ }; struct sk_security_struct { diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 39337af..a33437b 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -77,8 +77,7 @@ int security_get_user_sids(u32 callsid, char *username, int security_port_sid(u16 domain, u16 type, u8 protocol, u16 port, u32 *out_sid); -int security_netif_sid(char *name, u32 *if_sid, - u32 *msg_sid); +int security_netif_sid(char *name, u32 *if_sid); int security_node_sid(u16 domain, void *addr, u32 addrlen, u32 *out_sid); diff --git a/security/selinux/netif.c b/security/selinux/netif.c index e87ab94..ee49a73 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c @@ -7,6 +7,8 @@ * Author: James Morris <[EMAIL PROTECTED]> * * Copyright (C) 2003 Red Hat, Inc., James Morris <[EMAIL PROTECTED]> + * Copyright (C) 2007 Hewlett-Packard Development Company, L.P. + *Paul Moore <[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, @@ -29,14 +31,6 @@ #define SEL_NETIF_HASH_SIZE64 #define SEL_NETIF_HASH_MAX 1024 -#undef DEBUG - -#ifdef DEBUG -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - struct sel_netif { struct list_head list; @@ -49,174 +43,217 @@ static LIST_HEAD(sel_netif_list); static DEFINE_SPINLOCK(sel_netif_lock); static struct list_head sel_netif_hash[SEL_NETIF_HASH_SIZE]; -static inline u32 sel_netif_hasfn(struct net_device *dev) +/** + * sel_netif_hashfn - Hashing function for the interface table + * @ifindex: the network interface + * + * Description: + * This is the hashing function for the network interface table, it returns the + * bucket number for the give
[RFC PATCH v9 15/18] SELinux: Allow NetLabel to directly cache SIDs
Now that the SELinux NetLabel "base SID" is always the netmsg initial SID we can do a big optimization - caching the SID and not just the MLS attributes. This not only saves a lot of per-packet memory allocations and copies but it has a nice side effect of removing a chunk of code. Signed-off-by: Paul Moore <[EMAIL PROTECTED]> --- security/selinux/hooks.c|6 -- security/selinux/include/netlabel.h |2 - security/selinux/include/security.h |2 - security/selinux/netlabel.c | 55 ++-- security/selinux/ss/services.c | 124 ++- 5 files changed, 55 insertions(+), 134 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 90b0901..d16f586 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3231,11 +3231,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) u32 nlbl_type; selinux_skb_xfrm_sid(skb, &xfrm_sid); - selinux_netlbl_skbuff_getsid(skb, -family, -SECINITSID_NETMSG, -&nlbl_type, -&nlbl_sid); + selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid); if (security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index c8c05a6..00a2809 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h @@ -48,7 +48,6 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, -u32 base_sid, u32 *type, u32 *sid); @@ -89,7 +88,6 @@ static inline void selinux_netlbl_sk_security_clone( static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, - u32 base_sid, u32 *type, u32 *sid) { diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 9347e2d..23137c1 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -124,7 +124,6 @@ int security_genfs_sid(const char *fstype, char *name, u16 sclass, #ifdef CONFIG_NETLABEL int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, - u32 base_sid, u32 *sid); int security_netlbl_sid_to_secattr(u32 sid, @@ -132,7 +131,6 @@ int security_netlbl_sid_to_secattr(u32 sid, #else static inline int security_netlbl_secattr_to_sid( struct netlbl_lsm_secattr *secattr, - u32 base_sid, u32 *sid) { return -EIDRM; diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index af78cb9..e07adf9 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -36,6 +36,33 @@ #include "security.h" /** + * selinux_netlbl_sidlookup_cached - Cache a SID lookup + * @skb: the packet + * @secattr: the NetLabel security attributes + * @sid: the SID + * + * Description: + * Query the SELinux security server to lookup the correct SID for the given + * security attributes. If the query is successful, cache the result to speed + * up future lookups. Returns zero on success, negative values on failure. + * + */ +static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, + struct netlbl_lsm_secattr *secattr, + u32 *sid) +{ + int rc; + + rc = security_netlbl_secattr_to_sid(secattr, sid); + if (rc == 0 && + (secattr->flags & NETLBL_SECATTR_CACHEABLE) && + (secattr->flags & NETLBL_SECATTR_CACHE)) + netlbl_cache_add(skb, secattr); + + return rc; +} + +/** * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism * @sk: the socket to label * @sid: the SID to use @@ -141,7 +168,6 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel * @skb: the packet * @family: protocol family - * @base_sid: the SELinux SID to use as a context for MLS only attributes * @type: NetLabel labeling protocol type * @sid: the SID * @@ -153,7 +179,6 @@ void selinux_netlbl_sk_security_clone(struct sk_secur
[RFC PATCH v9 04/18] NetLabel: Add secid token support to the NetLabel secattr struct
This patch adds support to the NetLabel LSM secattr struct for a secid token and a type field, paving the way for full LSM/SELinux context support and "static" or "fallback" labels. In addition, this patch adds a fair amount of documentation to the core NetLabel structures used as part of the NetLabel kernel API. Signed-off-by: Paul Moore <[EMAIL PROTECTED]> --- include/net/netlabel.h| 91 ++--- net/ipv4/cipso_ipv4.c | 59 +++- net/netlabel/netlabel_unlabeled.c |1 security/selinux/ss/mls.c | 10 ++-- security/selinux/ss/services.c|5 ++ 5 files changed, 120 insertions(+), 46 deletions(-) diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 2e5b2f6..18b73cf 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -105,17 +105,49 @@ struct netlbl_dom_map; /* Domain mapping operations */ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info); -/* LSM security attributes */ +/* + * LSM security attributes + */ + +/** + * struct netlbl_lsm_cache - NetLabel LSM security attribute cache + * @refcount: atomic reference counter + * @free: LSM supplied function to free the cache data + * @data: LSM supplied cache data + * + * Description: + * This structure is provided for LSMs which wish to make use of the NetLabel + * caching mechanism to store LSM specific data/attributes in the NetLabel + * cache. If the LSM has to perform a lot of translation from the NetLabel + * security attributes into it's own internal representation then the cache + * mechanism can provide a way to eliminate some or all of that translation + * overhead on a cache hit. + * + */ struct netlbl_lsm_cache { atomic_t refcount; void (*free) (const void *data); void *data; }; -/* The catmap bitmap field MUST be a power of two in length and large + +/** + * struct netlbl_lsm_secattr_catmap - NetLabel LSM secattr category bitmap + * @startbit: the value of the lowest order bit in the bitmap + * @bitmap: the category bitmap + * @next: pointer to the next bitmap "node" or NULL + * + * Description: + * This structure is used to represent category bitmaps. Due to the large + * number of categories supported by most labeling protocols it is not + * practical to transfer a full bitmap internally so NetLabel adopts a sparse + * bitmap structure modeled after SELinux's ebitmap structure. + * The catmap bitmap field MUST be a power of two in length and large * enough to hold at least 240 bits. Special care (i.e. check the code!) * should be used when changing these values as the LSM implementation * probably has functions which rely on the sizes of these types to speed - * processing. */ + * processing. + * + */ #define NETLBL_CATMAP_MAPTYPE u64 #define NETLBL_CATMAP_MAPCNT4 #define NETLBL_CATMAP_MAPSIZE (sizeof(NETLBL_CATMAP_MAPTYPE) * 8) @@ -127,22 +159,48 @@ struct netlbl_lsm_secattr_catmap { NETLBL_CATMAP_MAPTYPE bitmap[NETLBL_CATMAP_MAPCNT]; struct netlbl_lsm_secattr_catmap *next; }; + +/** + * struct netlbl_lsm_secattr - NetLabel LSM security attributes + * @flags: indicate which attributes are contained in this structure + * @type: indicate the NLTYPE of the attributes + * @domain: the NetLabel LSM domain + * @cache: NetLabel LSM specific cache + * @attr.mls: MLS sensitivity label + * @attr.mls.cat: MLS category bitmap + * @attr.mls.lvl: MLS sensitivity level + * @attr.secid: LSM specific secid token + * + * Description: + * This structure is used to pass security attributes between NetLabel and the + * LSM modules. The flags field is used to specify which fields within the + * struct are valid and valid values can be created by bitwise OR'ing the + * NETLBL_SECATTR_* defines. The domain field is typically set by the LSM to + * specify domain specific configuration settings and is not usually used by + * NetLabel itself when returning security attributes to the LSM. + * + */ #define NETLBL_SECATTR_NONE 0x #define NETLBL_SECATTR_DOMAIN 0x0001 #define NETLBL_SECATTR_CACHE0x0002 #define NETLBL_SECATTR_MLS_LVL 0x0004 #define NETLBL_SECATTR_MLS_CAT 0x0008 +#define NETLBL_SECATTR_SECID0x0010 #define NETLBL_SECATTR_CACHEABLE(NETLBL_SECATTR_MLS_LVL | \ -NETLBL_SECATTR_MLS_CAT) +NETLBL_SECATTR_MLS_CAT | \ +NETLBL_SECATTR_SECID) struct netlbl_lsm_secattr { u32 flags; - + u32 type; char *domain; - - u32 mls_lvl; - struct netlbl_lsm_secattr_catmap *mls_cat; - struct netlbl_lsm_cache *cache; + union { + struct { + struct netlbl_lsm_secattr_catmap *cat; +
[RFC PATCH v9 07/18] NetLabel: Add IP address family information to the netlbl_skbuff_getattr() function
In order to do any sort of IP header inspection of incoming packets we need to know which address family, AF_INET/AF_INET6/etc., it belongs to and since the sk_buff structure does not store this information we need to pass along the address family separate from the packet itself. Signed-off-by: Paul Moore <[EMAIL PROTECTED]> --- include/net/netlabel.h |2 ++ net/netlabel/netlabel_kapi.c|2 ++ security/selinux/hooks.c| 33 ++--- security/selinux/include/netlabel.h |8 +++- security/selinux/netlabel.c | 12 +--- 5 files changed, 42 insertions(+), 15 deletions(-) diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 18b73cf..a3bffb4 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -363,6 +363,7 @@ int netlbl_sock_setattr(struct sock *sk, int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr); int netlbl_skbuff_getattr(const struct sk_buff *skb, + u16 family, struct netlbl_lsm_secattr *secattr); void netlbl_skbuff_err(struct sk_buff *skb, int error); @@ -415,6 +416,7 @@ static inline int netlbl_sock_getattr(struct sock *sk, return -ENOSYS; } static inline int netlbl_skbuff_getattr(const struct sk_buff *skb, + u16 family, struct netlbl_lsm_secattr *secattr) { return -ENOSYS; diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index d3762ea..4914615 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -332,6 +332,7 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) /** * netlbl_skbuff_getattr - Determine the security attributes of a packet * @skb: the packet + * @family: protocol family * @secattr: the security attributes * * Description: @@ -342,6 +343,7 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) * */ int netlbl_skbuff_getattr(const struct sk_buff *skb, + u16 family, struct netlbl_lsm_secattr *secattr) { if (CIPSO_V4_OPTEXIST(skb) && diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8bb673b..7b99d52 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3192,6 +3192,7 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, /** * selinux_skb_extlbl_sid - Determine the external label of a packet * @skb: the packet + * @family: protocol family * @sid: the packet's SID * * Description: @@ -3204,13 +3205,16 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, * selinux_netlbl_skbuff_getsid(). * */ -static void selinux_skb_extlbl_sid(struct sk_buff *skb, u32 *sid) +static void selinux_skb_extlbl_sid(struct sk_buff *skb, + u16 family, + u32 *sid) { u32 xfrm_sid; u32 nlbl_sid; selinux_skb_xfrm_sid(skb, &xfrm_sid); if (selinux_netlbl_skbuff_getsid(skb, +family, (xfrm_sid == SECSID_NULL ? SECINITSID_NETMSG : xfrm_sid), &nlbl_sid) != 0) @@ -3703,7 +3707,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) if (err) goto out; - err = selinux_netlbl_sock_rcv_skb(sksec, skb, &ad); + err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad); if (err) goto out; @@ -3759,18 +3763,25 @@ out: static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) { u32 peer_secid = SECSID_NULL; - int err = 0; + u16 family; - if (sock && sock->sk->sk_family == PF_UNIX) + if (sock) + family = sock->sk->sk_family; + else if (skb && skb->sk) + family = skb->sk->sk_family; + else + goto out; + + if (sock && family == PF_UNIX) selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); else if (skb) - selinux_skb_extlbl_sid(skb, &peer_secid); + selinux_skb_extlbl_sid(skb, family, &peer_secid); - if (peer_secid == SECSID_NULL) - err = -EINVAL; +out: *secid = peer_secid; - - return err; + if (peer_secid == SECSID_NULL) + return -EINVAL; + return 0; } static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) @@ -3825,7 +3836,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *
[RFC PATCH v9 01/18] NetLabel: Remove unneeded RCU read locks
This patch removes some unneeded RCU read locks as we can treat the reads as "safe" even without RCU. It also converts the NetLabel configuration refcount from a spinlock protected u32 into atomic_t to be more consistent with the rest of the kernel. Signed-off-by: Paul Moore <[EMAIL PROTECTED]> --- net/netlabel/netlabel_cipso_v4.c |5 ++- net/netlabel/netlabel_kapi.c |3 +- net/netlabel/netlabel_mgmt.c | 63 ++--- net/netlabel/netlabel_mgmt.h |7 ++-- net/netlabel/netlabel_unlabeled.c | 22 ++--- 5 files changed, 15 insertions(+), 85 deletions(-) diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index ba0ca8d..becf91a 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "netlabel_user.h" #include "netlabel_cipso_v4.h" @@ -421,7 +422,7 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info) break; } if (ret_val == 0) - netlbl_mgmt_protocount_inc(); + atomic_inc(&netlabel_mgmt_protocount); audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD, &audit_info); @@ -698,7 +699,7 @@ static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info) &audit_info, netlbl_cipsov4_doi_free); if (ret_val == 0) - netlbl_mgmt_protocount_dec(); + atomic_dec(&netlabel_mgmt_protocount); audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_DEL, &audit_info); diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 4f50949..d3762ea 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "netlabel_domainhash.h" #include "netlabel_unlabeled.h" @@ -262,7 +263,7 @@ int netlbl_enabled(void) /* At some point we probably want to expose this mechanism to the user * as well so that admins can toggle NetLabel regardless of the * configuration */ - return (netlbl_mgmt_protocount_value() > 0 ? 1 : 0); + return (atomic_read(&netlabel_mgmt_protocount) > 0); } /** diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index 5648337..e2258dc 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c @@ -37,14 +37,14 @@ #include #include #include +#include #include "netlabel_domainhash.h" #include "netlabel_user.h" #include "netlabel_mgmt.h" -/* NetLabel configured protocol count */ -static DEFINE_SPINLOCK(netlabel_mgmt_protocount_lock); -static u32 netlabel_mgmt_protocount = 0; +/* NetLabel configured protocol counter */ +atomic_t netlabel_mgmt_protocount = ATOMIC_INIT(0); /* Argument struct for netlbl_domhsh_walk() */ struct netlbl_domhsh_walk_arg { @@ -71,63 +71,6 @@ static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = { }; /* - * NetLabel Misc Managment Functions - */ - -/** - * netlbl_mgmt_protocount_inc - Increment the configured labeled protocol count - * - * Description: - * Increment the number of labeled protocol configurations in the current - * NetLabel configuration. Keep track of this for use in determining if - * NetLabel label enforcement should be active/enabled or not in the LSM. - * - */ -void netlbl_mgmt_protocount_inc(void) -{ - spin_lock(&netlabel_mgmt_protocount_lock); - netlabel_mgmt_protocount++; - spin_unlock(&netlabel_mgmt_protocount_lock); -} - -/** - * netlbl_mgmt_protocount_dec - Decrement the configured labeled protocol count - * - * Description: - * Decrement the number of labeled protocol configurations in the current - * NetLabel configuration. Keep track of this for use in determining if - * NetLabel label enforcement should be active/enabled or not in the LSM. - * - */ -void netlbl_mgmt_protocount_dec(void) -{ - spin_lock(&netlabel_mgmt_protocount_lock); - if (netlabel_mgmt_protocount > 0) - netlabel_mgmt_protocount--; - spin_unlock(&netlabel_mgmt_protocount_lock); -} - -/** - * netlbl_mgmt_protocount_value - Return the number of configured protocols - * - * Description: - * Return the number of labeled protocols in the current NetLabel - * configuration. This value is useful in determining if NetLabel label - * enforcement should be active/enabled or not in the LSM. - * - */ -u32 netlbl_mgmt_protocount_value(void) -{ - u32 val; - - rcu_read_lock(); - val = netlabel_mgmt_protocount; - rcu_read_unlock(); - - return va
[RFC PATCH v9 06/18] LSM: Add inet_sys_snd_skb() LSM hook
Add an inet_sys_snd_skb() LSM hook to allow the LSM to provide packet level access control for all outbound packets. Using the existing postroute_last netfilter hook turns out to be problematic as it is can be invoked multiple times for a single packet, e.g. individual IPsec transforms, adding unwanted overhead and complicating the security policy. Signed-off-by: Paul Moore <[EMAIL PROTECTED]> --- include/linux/security.h | 11 +++ net/ipv4/ip_output.c |7 +++ net/ipv6/ip6_output.c|5 + security/dummy.c |8 +++- security/security.c |6 ++ 5 files changed, 36 insertions(+), 1 deletions(-) diff --git a/include/linux/security.h b/include/linux/security.h index db19c92..1b8d332 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -876,6 +876,10 @@ struct request_sock; * Sets the connection's peersid to the secmark on skb. * @req_classify_flow: * Sets the flow's sid to the openreq sid. + * @inet_sys_snd_skb: + * Check permissions on outgoing network packets. + * @skb is the packet to check + * @family is the packet's address family * * Security hooks for XFRM operations. * @@ -1416,6 +1420,7 @@ struct security_operations { void (*inet_csk_clone)(struct sock *newsk, const struct request_sock *req); void (*inet_conn_established)(struct sock *sk, struct sk_buff *skb); void (*req_classify_flow)(const struct request_sock *req, struct flowi *fl); + int (*inet_sys_snd_skb)(struct sk_buff *skb, int family); #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM @@ -2328,6 +2333,7 @@ void security_sk_free(struct sock *sk); void security_sk_clone(const struct sock *sk, struct sock *newsk); void security_sk_classify_flow(struct sock *sk, struct flowi *fl); void security_req_classify_flow(const struct request_sock *req, struct flowi *fl); +int security_inet_sys_snd_skb(struct sk_buff *skb, int family); void security_sock_graft(struct sock*sk, struct socket *parent); int security_inet_conn_request(struct sock *sk, struct sk_buff *skb, struct request_sock *req); @@ -2471,6 +2477,11 @@ static inline void security_req_classify_flow(const struct request_sock *req, st { } +static inline int security_inet_sys_snd_skb(struct sk_buff *skb, int family) +{ + return 0; +} + static inline void security_sock_graft(struct sock* sk, struct socket *parent) { } diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index fd99fbd..82a7297 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -204,6 +204,8 @@ static inline int ip_skb_dst_mtu(struct sk_buff *skb) static int ip_finish_output(struct sk_buff *skb) { + int err; + #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) /* Policy lookup after SNAT yielded a new policy */ if (skb->dst->xfrm != NULL) { @@ -211,6 +213,11 @@ static int ip_finish_output(struct sk_buff *skb) return dst_output(skb); } #endif + + err = security_inet_sys_snd_skb(skb, AF_INET); + if (err) + return err; + if (skb->len > ip_skb_dst_mtu(skb) && !skb_is_gso(skb)) return ip_fragment(skb, ip_finish_output2); else diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 6338a9c..44ddf32 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -72,8 +72,13 @@ static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *f static int ip6_output_finish(struct sk_buff *skb) { + int err; struct dst_entry *dst = skb->dst; + err = security_inet_sys_snd_skb(skb, AF_INET6); + if (err) + return err; + if (dst->hh) return neigh_hh_output(dst->hh, skb); else if (dst->neighbour) diff --git a/security/dummy.c b/security/dummy.c index 0b62f95..384979a 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -848,6 +848,11 @@ static inline void dummy_req_classify_flow(const struct request_sock *req, struct flowi *fl) { } + +static inline int dummy_inet_sys_snd_skb(struct sk_buff *skb, int family) +{ + return 0; +} #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM @@ -1122,7 +1127,8 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, inet_csk_clone); set_to_dummy_if_null(ops, inet_conn_established); set_to_dummy_if_null(ops, req_classify_flow); - #endif/* CONFIG_SECURITY_NETWORK */ + set_to_dummy_if_null(ops, inet_sys_snd_skb); +#endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM set_to_dummy_if_null(ops, xfrm_policy_alloc_security); set_to_dummy_if_null(ops, xfrm_policy_clone_security); diff --git a/security/security.c b/security/security.c index 3bdcada..7f554
[RFC PATCH v9 02/18] NetLabel: Cleanup the LSM domain hash functions
The NetLabel/LSM domain hash table search function used an argument to specify if the default entry should be returned if an exact match couldn't be found in the hash table. This is a bit against the kernel's style so make two separate functions to represent the separate behaviors. Signed-off-by: Paul Moore <[EMAIL PROTECTED]> --- net/netlabel/netlabel_domainhash.c | 47 ++-- 1 files changed, 34 insertions(+), 13 deletions(-) diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index b3675bd..1f8f7ac 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c @@ -109,17 +109,14 @@ static u32 netlbl_domhsh_hash(const char *key) /** * netlbl_domhsh_search - Search for a domain entry * @domain: the domain - * @def: return default if no match is found * * Description: * Searches the domain hash table and returns a pointer to the hash table - * entry if found, otherwise NULL is returned. If @def is non-zero and a - * match is not found in the domain hash table the default mapping is returned - * if it exists. The caller is responsibile for the rcu hash table locks - * (i.e. the caller much call rcu_read_[un]lock()). + * entry if found, otherwise NULL is returned. The caller is responsibile for + * the rcu hash table locks (i.e. the caller much call rcu_read_[un]lock()). * */ -static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain, u32 def) +static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain) { u32 bkt; struct netlbl_dom_map *iter; @@ -133,10 +130,31 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain, u32 def) return iter; } - if (def != 0) { - iter = rcu_dereference(netlbl_domhsh_def); - if (iter != NULL && iter->valid) - return iter; + return NULL; +} + +/** + * netlbl_domhsh_search_def - Search for a domain entry + * @domain: the domain + * @def: return default if no match is found + * + * Description: + * Searches the domain hash table and returns a pointer to the hash table + * entry if an exact match is found, if an exact match is not present in the + * hash table then the default entry is returned if valid otherwise NULL is + * returned. The caller is responsibile for the rcu hash table locks + * (i.e. the caller much call rcu_read_[un]lock()). + * + */ +static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain) +{ + struct netlbl_dom_map *entry; + + entry = netlbl_domhsh_search(domain); + if (entry == NULL) { + entry = rcu_dereference(netlbl_domhsh_def); + if (entry != NULL && entry->valid) + return entry; } return NULL; @@ -224,7 +242,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, if (entry->domain != NULL) { bkt = netlbl_domhsh_hash(entry->domain); spin_lock(&netlbl_domhsh_lock); - if (netlbl_domhsh_search(entry->domain, 0) == NULL) + if (netlbl_domhsh_search(entry->domain) == NULL) list_add_tail_rcu(&entry->list, &rcu_dereference(netlbl_domhsh)->tbl[bkt]); else @@ -307,7 +325,10 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) struct audit_buffer *audit_buf; rcu_read_lock(); - entry = netlbl_domhsh_search(domain, (domain != NULL ? 0 : 1)); + if (domain) + entry = netlbl_domhsh_search(domain); + else + entry = netlbl_domhsh_search_def(domain); if (entry == NULL) goto remove_return; switch (entry->type) { @@ -377,7 +398,7 @@ int netlbl_domhsh_remove_default(struct netlbl_audit *audit_info) */ struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain) { - return netlbl_domhsh_search(domain, 1); + return netlbl_domhsh_search_def(domain); } /** - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v9 00/18] Labeled networking patches for 2.6.25 (against 2.6.24-rc6)
One more revision before the end of the year, backed against 2.6.24-rc6 or rather Linus' linux-2.6 tree from an hour ago. The changes this time are pretty minor: some IPv6 address tweaks and the object class/permission changes already discussed on the SELinux list. I've also update the git tree available here: * git://git.infradead.org/users/pcmoore/lblnet-2.6_testing -- paul moore linux security @ hp - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v9 03/18] NetLabel: Consolidate the LSM domain mapping/hashing locks
Currently we use two separate spinlocks to protect both the hash/mapping table and the default entry. This could be considered a bit foolish because it adds complexity without offering any real performance advantage. This patch removes the dedicated default spinlock and protects the default entry with the hash/mapping table spinlock. Signed-off-by: Paul Moore <[EMAIL PROTECTED]> --- net/netlabel/netlabel_domainhash.c | 30 +- 1 files changed, 9 insertions(+), 21 deletions(-) diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index 1f8f7ac..9a8ea01 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c @@ -54,9 +54,6 @@ struct netlbl_domhsh_tbl { * hash table should be okay */ static DEFINE_SPINLOCK(netlbl_domhsh_lock); static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL; - -/* Default domain mapping */ -static DEFINE_SPINLOCK(netlbl_domhsh_def_lock); static struct netlbl_dom_map *netlbl_domhsh_def = NULL; /* @@ -239,24 +236,22 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, INIT_RCU_HEAD(&entry->rcu); rcu_read_lock(); + spin_lock(&netlbl_domhsh_lock); if (entry->domain != NULL) { bkt = netlbl_domhsh_hash(entry->domain); - spin_lock(&netlbl_domhsh_lock); if (netlbl_domhsh_search(entry->domain) == NULL) list_add_tail_rcu(&entry->list, &rcu_dereference(netlbl_domhsh)->tbl[bkt]); else ret_val = -EEXIST; - spin_unlock(&netlbl_domhsh_lock); } else { INIT_LIST_HEAD(&entry->list); - spin_lock(&netlbl_domhsh_def_lock); if (rcu_dereference(netlbl_domhsh_def) == NULL) rcu_assign_pointer(netlbl_domhsh_def, entry); else ret_val = -EEXIST; - spin_unlock(&netlbl_domhsh_def_lock); } + spin_unlock(&netlbl_domhsh_lock); audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info); if (audit_buf != NULL) { audit_log_format(audit_buf, @@ -337,23 +332,16 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) entry->domain); break; } - if (entry != rcu_dereference(netlbl_domhsh_def)) { - spin_lock(&netlbl_domhsh_lock); - if (entry->valid) { - entry->valid = 0; + spin_lock(&netlbl_domhsh_lock); + if (entry->valid) { + entry->valid = 0; + if (entry != rcu_dereference(netlbl_domhsh_def)) list_del_rcu(&entry->list); - ret_val = 0; - } - spin_unlock(&netlbl_domhsh_lock); - } else { - spin_lock(&netlbl_domhsh_def_lock); - if (entry->valid) { - entry->valid = 0; + else rcu_assign_pointer(netlbl_domhsh_def, NULL); - ret_val = 0; - } - spin_unlock(&netlbl_domhsh_def_lock); + ret_val = 0; } + spin_unlock(&netlbl_domhsh_lock); audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_DEL, audit_info); if (audit_buf != NULL) { - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v9 05/18] LSM: Add secctx_to_secid() LSM hook
Add a secctx_to_secid() LSM hook to go along with the existing secid_to_secctx() LSM hook. This patch also includes the SELinux implementation for this hook. Signed-off-by: Paul Moore <[EMAIL PROTECTED]> Acked-by: Stephen Smalley <[EMAIL PROTECTED]> --- include/linux/security.h | 13 + security/dummy.c |6 ++ security/security.c |6 ++ security/selinux/hooks.c |6 ++ 4 files changed, 31 insertions(+), 0 deletions(-) diff --git a/include/linux/security.h b/include/linux/security.h index ac05083..db19c92 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1183,6 +1183,10 @@ struct request_sock; * Convert secid to security context. * @secid contains the security ID. * @secdata contains the pointer that stores the converted security context. + * @secctx_to_secid: + * Convert security context to secid. + * @secid contains the pointer to the generated security ID. + * @secdata contains the security context. * * @release_secctx: * Release the security context. @@ -1371,6 +1375,7 @@ struct security_operations { int (*getprocattr)(struct task_struct *p, char *name, char **value); int (*setprocattr)(struct task_struct *p, char *name, void *value, size_t size); int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen); + int (*secctx_to_secid)(char *secdata, u32 seclen, u32 *secid); void (*release_secctx)(char *secdata, u32 seclen); #ifdef CONFIG_SECURITY_NETWORK @@ -1603,6 +1608,7 @@ int security_setprocattr(struct task_struct *p, char *name, void *value, size_t int security_netlink_send(struct sock *sk, struct sk_buff *skb); int security_netlink_recv(struct sk_buff *skb, int cap); int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); +int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid); void security_release_secctx(char *secdata, u32 seclen); #else /* CONFIG_SECURITY */ @@ -2280,6 +2286,13 @@ static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *secle return -EOPNOTSUPP; } +static inline int security_secctx_to_secid(char *secdata, + u32 seclen, + u32 *secid) +{ + return -EOPNOTSUPP; +} + static inline void security_release_secctx(char *secdata, u32 seclen) { } diff --git a/security/dummy.c b/security/dummy.c index 3ccfbbe..0b62f95 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -928,6 +928,11 @@ static int dummy_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) return -EOPNOTSUPP; } +static int dummy_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) +{ + return -EOPNOTSUPP; +} + static void dummy_release_secctx(char *secdata, u32 seclen) { } @@ -1086,6 +1091,7 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, getprocattr); set_to_dummy_if_null(ops, setprocattr); set_to_dummy_if_null(ops, secid_to_secctx); + set_to_dummy_if_null(ops, secctx_to_secid); set_to_dummy_if_null(ops, release_secctx); #ifdef CONFIG_SECURITY_NETWORK set_to_dummy_if_null(ops, unix_stream_connect); diff --git a/security/security.c b/security/security.c index 0e1f1f1..3bdcada 100644 --- a/security/security.c +++ b/security/security.c @@ -816,6 +816,12 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) } EXPORT_SYMBOL(security_secid_to_secctx); +int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) +{ + return security_ops->secctx_to_secid(secdata, seclen, secid); +} +EXPORT_SYMBOL(security_secctx_to_secid); + void security_release_secctx(char *secdata, u32 seclen) { return security_ops->release_secctx(secdata, seclen); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 9f3124b..8bb673b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4710,6 +4710,11 @@ static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) return security_sid_to_context(secid, secdata, seclen); } +static int selinux_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) +{ + return security_context_to_sid(secdata, seclen, secid); +} + static void selinux_release_secctx(char *secdata, u32 seclen) { kfree(secdata); @@ -4898,6 +4903,7 @@ static struct security_operations selinux_ops = { .setprocattr = selinux_setprocattr, .secid_to_secctx = selinux_secid_to_secctx, + .secctx_to_secid = selinux_secctx_to_secid, .release_secctx = selinux_release_secctx, .unix_stream_connect = selinux_socket_unix_stream_connect, - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED]
[RFC PATCH v9 12/18] SELinux: Add a new peer class and permissions to the Flask definitions
Add additional Flask definitions to support the new "peer" object class and additional permissions to the netif and node object classes. Signed-off-by: Paul Moore <[EMAIL PROTECTED]> --- security/selinux/include/av_perm_to_string.h |5 + security/selinux/include/av_permissions.h|5 + security/selinux/include/class_to_string.h |7 +++ security/selinux/include/flask.h |1 + 4 files changed, 18 insertions(+), 0 deletions(-) diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h index 049bf69..caa0634 100644 --- a/security/selinux/include/av_perm_to_string.h +++ b/security/selinux/include/av_perm_to_string.h @@ -37,6 +37,8 @@ S_(SECCLASS_NODE, NODE__ENFORCE_DEST, "enforce_dest") S_(SECCLASS_NODE, NODE__DCCP_RECV, "dccp_recv") S_(SECCLASS_NODE, NODE__DCCP_SEND, "dccp_send") + S_(SECCLASS_NODE, NODE__RECVFROM, "recvfrom") + S_(SECCLASS_NODE, NODE__SENDTO, "sendto") S_(SECCLASS_NETIF, NETIF__TCP_RECV, "tcp_recv") S_(SECCLASS_NETIF, NETIF__TCP_SEND, "tcp_send") S_(SECCLASS_NETIF, NETIF__UDP_RECV, "udp_recv") @@ -45,6 +47,8 @@ S_(SECCLASS_NETIF, NETIF__RAWIP_SEND, "rawip_send") S_(SECCLASS_NETIF, NETIF__DCCP_RECV, "dccp_recv") S_(SECCLASS_NETIF, NETIF__DCCP_SEND, "dccp_send") + S_(SECCLASS_NETIF, NETIF__INGRESS, "ingress") + S_(SECCLASS_NETIF, NETIF__EGRESS, "egress") S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto") S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn") S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__ACCEPTFROM, "acceptfrom") @@ -159,3 +163,4 @@ S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind") S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect") S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero") + S_(SECCLASS_PEER, PEER__RECV, "recv") diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h index eda89a2..c2b5bb2 100644 --- a/security/selinux/include/av_permissions.h +++ b/security/selinux/include/av_permissions.h @@ -292,6 +292,8 @@ #define NODE__ENFORCE_DEST0x0040UL #define NODE__DCCP_RECV 0x0080UL #define NODE__DCCP_SEND 0x0100UL +#define NODE__RECVFROM0x0200UL +#define NODE__SENDTO 0x0400UL #define NETIF__TCP_RECV 0x0001UL #define NETIF__TCP_SEND 0x0002UL #define NETIF__UDP_RECV 0x0004UL @@ -300,6 +302,8 @@ #define NETIF__RAWIP_SEND 0x0020UL #define NETIF__DCCP_RECV 0x0040UL #define NETIF__DCCP_SEND 0x0080UL +#define NETIF__INGRESS0x0100UL +#define NETIF__EGRESS 0x0200UL #define NETLINK_SOCKET__IOCTL 0x0001UL #define NETLINK_SOCKET__READ 0x0002UL #define NETLINK_SOCKET__WRITE 0x0004UL @@ -824,3 +828,4 @@ #define DCCP_SOCKET__NODE_BIND0x0040UL #define DCCP_SOCKET__NAME_CONNECT 0x0080UL #define MEMPROTECT__MMAP_ZERO 0x0001UL +#define PEER__RECV0x0001UL diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h index e77de0e..b1b0d1d 100644 --- a/security/selinux/include/class_to_string.h +++ b/security/selinux/include/class_to_string.h @@ -64,3 +64,10 @@ S_(NULL) S_("dccp_socket") S_("memprotect") +S_(NULL) +S_(NULL) +S_(NULL) +S_(NULL) +S_(NULL) +S_(NULL) +S_("peer") diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h index a9c2b20..09e9dd2 100644 --- a/security/selinux/include/flask.h +++ b/security/selinux/include/flask.h @@ -50,6 +50,7 @@ #define SECCLASS_KEY 58 #define SECCLASS_DCCP_SOCKET 60 #define SECCLASS_MEMPROTECT 61 +#define SECCLASS_PEER68 /* * Security identifier indices for initial entities - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v9 09/18] SELinux: Only store the network interface's ifindex
Instead of storing the packet's network interface name store the ifindex. This allows us to defer the need to lookup the net_device structure until the audit record is generated meaning that in the majority of cases we never need to bother with this at all. Signed-off-by: Paul Moore <[EMAIL PROTECTED]> --- security/selinux/avc.c | 15 --- security/selinux/hooks.c |4 ++-- security/selinux/include/avc.h |2 +- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 81b3dff..e8529e2 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -661,9 +661,18 @@ void avc_audit(u32 ssid, u32 tsid, "daddr", "dest"); break; } - if (a->u.net.netif) - audit_log_format(ab, " netif=%s", - a->u.net.netif); + if (a->u.net.netif > 0) { + struct net_device *dev; + + /* NOTE: we always use init's namespace */ + dev = dev_get_by_index(&init_net, + a->u.net.netif); + if (dev) { + audit_log_format(ab, " netif=%s", +dev->name); + dev_put(dev); + } + } break; } } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8336c93..b451b4c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3691,7 +3691,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) family = PF_INET; AVC_AUDIT_DATA_INIT(&ad, NET); - ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]"; + ad.u.net.netif = skb->iif; ad.u.net.family = family; err = selinux_parse_skb(skb, &ad, &addrp, &len, 1, NULL); @@ -4022,7 +4022,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum, sksec = sk->sk_security; AVC_AUDIT_DATA_INIT(&ad, NET); - ad.u.net.netif = dev->name; + ad.u.net.netif = dev->ifindex; ad.u.net.family = family; err = selinux_parse_skb(skb, &ad, &addrp, &len, 0, &proto); diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 553607a..80c28fa 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -51,7 +51,7 @@ struct avc_audit_data { struct inode *inode; } fs; struct { - char *netif; + int netif; struct sock *sk; u16 family; __be16 dport; - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH v9 14/18] SELinux: Enable dynamic enable/disable of the network access checks
This patch introduces a mechanism for checking when labeled IPsec or SECMARK are in use by keeping introducing a configuration reference counter for each subsystem. In the case of labeled IPsec, whenever a labeled SA or SPD entry is created the labeled IPsec/XFRM reference count is increased and when the entry is removed it is decreased. In the case of SECMARK, when a SECMARK target is created the reference count is increased and later decreased when the target is removed. These reference counters allow SELinux to quickly determine if either of these subsystems are enabled. NetLabel already has a similar mechanism which provides the netlbl_enabled() function. This patch also renames the selinux_relabel_packet_permission() function to selinux_secmark_relabel_packet_permission() as the original name and description were misleading in that they referenced a single packet label which is not the case. Signed-off-by: Paul Moore <[EMAIL PROTECTED]> --- include/linux/selinux.h | 45 +++--- net/netfilter/xt_SECMARK.c | 13 ++- security/selinux/exports.c | 20 +++-- security/selinux/hooks.c| 46 +++ security/selinux/include/xfrm.h | 12 ++ security/selinux/xfrm.c | 18 ++- 6 files changed, 132 insertions(+), 22 deletions(-) diff --git a/include/linux/selinux.h b/include/linux/selinux.h index 6080f73..8c2cc4c 100644 --- a/include/linux/selinux.h +++ b/include/linux/selinux.h @@ -120,16 +120,35 @@ void selinux_get_task_sid(struct task_struct *tsk, u32 *sid); int selinux_string_to_sid(char *str, u32 *sid); /** - * selinux_relabel_packet_permission - check permission to relabel a packet - * @sid: ID value to be applied to network packet (via SECMARK, most likely) + * selinux_secmark_relabel_packet_permission - secmark permission check + * @sid: SECMARK ID value to be applied to network packet * - * Returns 0 if the current task is allowed to label packets with the - * supplied security ID. Note that it is implicit that the packet is always - * being relabeled from the default unlabled value, and that the access - * control decision is made in the AVC. + * Returns 0 if the current task is allowed to set the SECMARK label of + * packets with the supplied security ID. Note that it is implicit that + * the packet is always being relabeled from the default unlabeled value, + * and that the access control decision is made in the AVC. */ -int selinux_relabel_packet_permission(u32 sid); +int selinux_secmark_relabel_packet_permission(u32 sid); +/** + * selinux_secmark_refcount_inc - increments the secmark use counter + * + * SELinux keeps track of the current SECMARK targets in use so it knows + * when to apply SECMARK label access checks to network packets. This + * function incements this reference count to indicate that a new SECMARK + * target has been configured. + */ +void selinux_secmark_refcount_inc(void); + +/** + * selinux_secmark_refcount_dec - decrements the secmark use counter + * + * SELinux keeps track of the current SECMARK targets in use so it knows + * when to apply SECMARK label access checks to network packets. This + * function decements this reference count to indicate that one of the + * existing SECMARK targets has been removed/flushed. + */ +void selinux_secmark_refcount_dec(void); #else static inline int selinux_audit_rule_init(u32 field, u32 op, @@ -184,11 +203,21 @@ static inline int selinux_string_to_sid(const char *str, u32 *sid) return 0; } -static inline int selinux_relabel_packet_permission(u32 sid) +static inline int selinux_secmark_relabel_packet_permission(u32 sid) { return 0; } +static inline void selinux_secmark_refcount_inc(void) +{ + return; +} + +static inline void selinux_secmark_refcount_dec(void) +{ + return; +} + #endif /* CONFIG_SECURITY_SELINUX */ #endif /* _LINUX_SELINUX_H */ diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c index 235806e..db4a1fe 100644 --- a/net/netfilter/xt_SECMARK.c +++ b/net/netfilter/xt_SECMARK.c @@ -72,12 +72,13 @@ static bool checkentry_selinux(struct xt_secmark_target_info *info) return false; } - err = selinux_relabel_packet_permission(sel->selsid); + err = selinux_secmark_relabel_packet_permission(sel->selsid); if (err) { printk(KERN_INFO PFX "unable to obtain relabeling permission\n"); return false; } + selinux_secmark_refcount_inc(); return true; } @@ -109,11 +110,20 @@ static bool checkentry(const char *tablename, const void *entry, return true; } +void destroy(const struct xt_target *target, void *targinfo) +{ + switch (mode) { + case SECMARK_MODE_SEL: + selinu
[RFC PATCH v9 11/18] SELinux: Add a capabilities bitmap to SELinux policy version 22
Add a new policy capabilities bitmap to SELinux policy version 22. This bitmap will enable the security server to query the policy to determine which features it supports. Signed-off-by: Paul Moore <[EMAIL PROTECTED]> --- security/selinux/Kconfig|2 - security/selinux/include/security.h | 15 ++ security/selinux/selinuxfs.c| 89 +-- security/selinux/ss/policydb.c | 18 +++ security/selinux/ss/policydb.h |2 + security/selinux/ss/services.c | 67 ++ 6 files changed, 185 insertions(+), 8 deletions(-) diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index b32a459..2b517d6 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig @@ -145,7 +145,7 @@ config SECURITY_SELINUX_POLICYDB_VERSION_MAX config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE int "NSA SELinux maximum supported policy format version value" depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX - range 15 21 + range 15 22 default 19 help This option sets the value for the maximum policy format version diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index a33437b..a22de97 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -25,13 +25,14 @@ #define POLICYDB_VERSION_MLS 19 #define POLICYDB_VERSION_AVTAB 20 #define POLICYDB_VERSION_RANGETRANS21 +#define POLICYDB_VERSION_POLCAP22 /* Range of policy versions we understand*/ #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE #else -#define POLICYDB_VERSION_MAX POLICYDB_VERSION_RANGETRANS +#define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP #endif struct netlbl_lsm_secattr; @@ -39,8 +40,19 @@ struct netlbl_lsm_secattr; extern int selinux_enabled; extern int selinux_mls_enabled; +/* Policy capabilities */ +enum { + POLICYDB_CAPABILITY_NETPEER, + __POLICYDB_CAPABILITY_MAX +}; +#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1) + +extern int selinux_policycap_netpeer; + int security_load_policy(void * data, size_t len); +int security_policycap_supported(unsigned int req_cap); + #define SEL_VEC_MAX 32 struct av_decision { u32 allowed; @@ -91,6 +103,7 @@ int security_get_classes(char ***classes, int *nclasses); int security_get_permissions(char *class, char ***perms, int *nperms); int security_get_reject_unknown(void); int security_get_allow_unknown(void); +int security_get_policycaps(int *len, int **values); #define SECURITY_FS_USE_XATTR 1 /* use xattr */ #define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */ diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 2fa483f..b87e9eb 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -2,6 +2,11 @@ * * Added conditional policy language extensions * + * Updated: Hewlett-Packard <[EMAIL PROTECTED]> + * + * Added support for the policy capability bitmap + * + * Copyright (C) 2007 Hewlett-Packard Development Company, L.P. * Copyright (C) 2003 - 2004 Tresys Technology, LLC * Copyright (C) 2004 Red Hat, Inc., James Morris <[EMAIL PROTECTED]> * This program is free software; you can redistribute it and/or modify @@ -35,6 +40,11 @@ #include "objsec.h" #include "conditional.h" +/* Policy capability filenames */ +static char *policycap_names[] = { + "network_peer_controls" +}; + unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; #ifdef CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT @@ -72,6 +82,9 @@ static int *bool_pending_values = NULL; static struct dentry *class_dir = NULL; static unsigned long last_class_ino; +/* global data for policy capabilities */ +static struct dentry *policycap_dir = NULL; + extern void selnl_notify_setenforce(int val); /* Check whether a task is allowed to use a security operation. */ @@ -111,10 +124,11 @@ enum sel_inos { static unsigned long sel_last_ino = SEL_INO_NEXT - 1; -#define SEL_INITCON_INO_OFFSET 0x0100 -#define SEL_BOOL_INO_OFFSET0x0200 -#define SEL_CLASS_INO_OFFSET 0x0400 -#define SEL_INO_MASK 0x00ff +#define SEL_INITCON_INO_OFFSET 0x0100 +#define SEL_BOOL_INO_OFFSET0x0200 +#define SEL_CLASS_INO_OFFSET 0x0400 +#define SEL_POLICYCAP_INO_OFFSET 0x0800 +#define SEL_INO_MASK 0x00ff #define TMPBUFLEN 12 static ssize_t sel_read_enforce(struct file *filp, char __user *buf, @@ -263,6 +277,7 @@ static const struct file_operations sel_policyvers_ops = { /* declaration for sel_w
[RFC PATCH v9 17/18] NetLabel: Add auditing to the static labeling mechanism
This patch adds auditing support to the NetLabel static labeling mechanism. Signed-off-by: Paul Moore <[EMAIL PROTECTED]> --- include/linux/audit.h |2 net/netlabel/netlabel_unlabeled.c | 207 ++--- 2 files changed, 195 insertions(+), 14 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index c687816..bdd6f5d 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -115,6 +115,8 @@ #define AUDIT_MAC_IPSEC_ADDSPD 1413/* Not used */ #define AUDIT_MAC_IPSEC_DELSPD 1414/* Not used */ #define AUDIT_MAC_IPSEC_EVENT 1415/* Audit an IPSec event */ +#define AUDIT_MAC_UNLBL_STCADD 1416/* NetLabel: add a static label */ +#define AUDIT_MAC_UNLBL_STCDEL 1417/* NetLabel: del a static label */ #define AUDIT_FIRST_KERN_ANOM_MSG 1700 #define AUDIT_LAST_KERN_ANOM_MSG1799 diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index d0c628c..42e81fd 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -147,6 +147,74 @@ static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1 }; /* + * Audit Helper Functions + */ + +/** + * netlbl_unlabel_audit_addr4 - Audit an IPv4 address + * @audit_buf: audit buffer + * @dev: network interface + * @addr: IP address + * @mask: IP address mask + * + * Description: + * Write the IPv4 address and address mask, if necessary, to @audit_buf. + * + */ +static void netlbl_unlabel_audit_addr4(struct audit_buffer *audit_buf, +const char *dev, +__be32 addr, __be32 mask) +{ + u32 mask_val = ntohl(mask); + + if (dev != NULL) + audit_log_format(audit_buf, " netif=%s", dev); + audit_log_format(audit_buf, " src=" NIPQUAD_FMT, NIPQUAD(addr)); + if (mask_val != 0x) { + u32 mask_len = 0; + while (mask_val > 0) { + mask_val <<= 1; + mask_len++; + } + audit_log_format(audit_buf, " src_prefixlen=%d", mask_len); + } +} + +/** + * netlbl_unlabel_audit_addr6 - Audit an IPv6 address + * @audit_buf: audit buffer + * @dev: network interface + * @addr: IP address + * @mask: IP address mask + * + * Description: + * Write the IPv6 address and address mask, if necessary, to @audit_buf. + * + */ +static void netlbl_unlabel_audit_addr6(struct audit_buffer *audit_buf, +const char *dev, +const struct in6_addr *addr, +const struct in6_addr *mask) +{ + if (dev != NULL) + audit_log_format(audit_buf, " netif=%s", dev); + audit_log_format(audit_buf, " src=" NIP6_FMT, NIP6(*addr)); + if (ntohl(mask->s6_addr32[3]) != 0x) { + u32 mask_len = 0; + u32 mask_val; + int iter = -1; + while (ntohl(mask->s6_addr32[++iter]) == 0x) + mask_len += 32; + mask_val = ntohl(mask->s6_addr32[iter]); + while (mask_val > 0) { + mask_val <<= 1; + mask_len++; + } + audit_log_format(audit_buf, " src_prefixlen=%d", mask_len); + } +} + +/* * Unlabeled Connection Hash Table Functions */ @@ -530,6 +598,7 @@ add_iface_failure: * @mask: address mask in network byte order * @addr_len: length of address/mask (4 for IPv4, 16 for IPv6) * @secid: LSM secid value for the entry + * @audit_info: NetLabel audit information * * Description: * Adds a new entry to the unlabeled connection hash table. Returns zero on @@ -541,12 +610,18 @@ static int netlbl_unlhsh_add(struct net *net, const void *addr, const void *mask, u32 addr_len, -u32 secid) +u32 secid, +struct netlbl_audit *audit_info) { int ret_val; int ifindex; struct net_device *dev; struct netlbl_unlhsh_iface *iface; + struct in_addr *addr4, *mask4; + struct in6_addr *addr6, *mask6; + struct audit_buffer *audit_buf = NULL; + char *secctx = NULL; + u32 secctx_len; if (addr_len != sizeof(struct in_addr) && addr_len != sizeof(struct in6_addr)) @@ -573,13 +648,28 @@ static int netlbl_unlhsh_add(struct net *net, goto unlhsh_add_return; } } + audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCADD, + audit_info); switch (addr_len) { case sizeof(struct in_addr): -
[RFC PATCH v9 16/18] NetLabel: Introduce static network labels for unlabeled connections
Most trusted OSs, with the exception of Linux, have the ability to specify static security labels for unlabeled networks. This patch adds this ability to the NetLabel packet labeling framework. If the NetLabel subsystem is called to determine the security attributes of an incoming packet it first checks to see if any recognized NetLabel packet labeling protocols are in-use on the packet. If none can be found then the unlabled connection table is queried and based on the packets incoming interface and address it is matched with a security label as configured by the administrator using the netlabel_tools package. The matching security label is returned to the caller just as if the packet was explicitly labeled using a labeling protocol. Signed-off-by: Paul Moore <[EMAIL PROTECTED]> --- include/net/netlabel.h|6 net/netlabel/netlabel_kapi.c | 16 net/netlabel/netlabel_unlabeled.c | 1375 + net/netlabel/netlabel_unlabeled.h | 145 4 files changed, 1524 insertions(+), 18 deletions(-) diff --git a/include/net/netlabel.h b/include/net/netlabel.h index a3bffb4..b3213c7 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -67,7 +67,11 @@ * NetLabel NETLINK protocol */ -#define NETLBL_PROTO_VERSION1 +/* NetLabel NETLINK protocol version + * 1: initial version + * 2: added static labels for unlabeled connections + */ +#define NETLBL_PROTO_VERSION2 /* NetLabel NETLINK types/families */ #define NETLBL_NLTYPE_NONE 0 diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 4914615..c69e3e1 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -312,7 +312,7 @@ socket_setattr_return: * @secattr: the security attributes * * Description: - * Examines the given sock to see any NetLabel style labeling has been + * Examines the given sock to see if any NetLabel style labeling has been * applied to the sock, if so it parses the socket label and returns the * security attributes in @secattr. Returns zero on success, negative values * on failure. @@ -320,13 +320,7 @@ socket_setattr_return: */ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) { - int ret_val; - - ret_val = cipso_v4_sock_getattr(sk, secattr); - if (ret_val == 0) - return 0; - - return netlbl_unlabel_getattr(secattr); + return cipso_v4_sock_getattr(sk, secattr); } /** @@ -350,7 +344,7 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb, cipso_v4_skbuff_getattr(skb, secattr) == 0) return 0; - return netlbl_unlabel_getattr(secattr); + return netlbl_unlabel_getattr(skb, family, secattr); } /** @@ -434,6 +428,10 @@ static int __init netlbl_init(void) if (ret_val != 0) goto init_failure; + ret_val = netlbl_unlabel_init(NETLBL_UNLHSH_BITSIZE); + if (ret_val != 0) + goto init_failure; + ret_val = netlbl_netlink_init(); if (ret_val != 0) goto init_failure; diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 7f5df0c..d0c628c 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -10,7 +10,7 @@ */ /* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 + * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - 2007 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,27 +29,99 @@ */ #include +#include #include #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include #include #include #include - +#include +#include +#include #include #include +#include #include "netlabel_user.h" #include "netlabel_domainhash.h" #include "netlabel_unlabeled.h" +#include "netlabel_mgmt.h" + +/* NOTE: at present we always use init's network namespace since we don't + * presently support different namespaces even though the majority of + * the functions in this file are "namespace safe" */ + +/* The unlabeled connection hash table which we use to map network interfaces + * and addresses of unlabeled packets to a user specified secid value for the + * LSM. The hash table is used to lookup the network interface entry + * (struct netlbl_unlhsh_iface) and then the interface entry is used to + * lookup an IP address match from an ordered list. If a network interface + * match can not be found in the hash table then the default entry + * (netlbl_unlhsh_def) is used. The IP address entry list + * (struct netlbl_unlhsh_addr) is ordered such that the entries with a + * larger netmask come first. + */ +struct n
Re: [RFC PATCH v9 12/18] SELinux: Add a new peer class and permissions to the Flask definitions
On Friday 21 December 2007 12:36:15 pm Stephen Smalley wrote: > On Fri, 2007-12-21 at 12:09 -0500, Paul Moore wrote: > > Add additional Flask definitions to support the new "peer" object class > > and additional permissions to the netif and node object classes. > > > > Signed-off-by: Paul Moore <[EMAIL PROTECTED]> > > Not an obstacle to merging, but need to get this reserved in policy too. Yep, I'm working on some policy patches now, although I'm not sure when I'll have those done. I'll post the FLASK definition changes today either way, that way they are at least there even if the policy rules aren't ready yet. > > --- > > > > security/selinux/include/av_perm_to_string.h |5 + > > security/selinux/include/av_permissions.h|5 + > > security/selinux/include/class_to_string.h |7 +++ > > security/selinux/include/flask.h |1 + > > 4 files changed, 18 insertions(+), 0 deletions(-) > > > > diff --git a/security/selinux/include/av_perm_to_string.h > > b/security/selinux/include/av_perm_to_string.h index 049bf69..caa0634 > > 100644 > > --- a/security/selinux/include/av_perm_to_string.h > > +++ b/security/selinux/include/av_perm_to_string.h > > @@ -37,6 +37,8 @@ > > S_(SECCLASS_NODE, NODE__ENFORCE_DEST, "enforce_dest") > > S_(SECCLASS_NODE, NODE__DCCP_RECV, "dccp_recv") > > S_(SECCLASS_NODE, NODE__DCCP_SEND, "dccp_send") > > + S_(SECCLASS_NODE, NODE__RECVFROM, "recvfrom") > > + S_(SECCLASS_NODE, NODE__SENDTO, "sendto") > > S_(SECCLASS_NETIF, NETIF__TCP_RECV, "tcp_recv") > > S_(SECCLASS_NETIF, NETIF__TCP_SEND, "tcp_send") > > S_(SECCLASS_NETIF, NETIF__UDP_RECV, "udp_recv") > > @@ -45,6 +47,8 @@ > > S_(SECCLASS_NETIF, NETIF__RAWIP_SEND, "rawip_send") > > S_(SECCLASS_NETIF, NETIF__DCCP_RECV, "dccp_recv") > > S_(SECCLASS_NETIF, NETIF__DCCP_SEND, "dccp_send") > > + S_(SECCLASS_NETIF, NETIF__INGRESS, "ingress") > > + S_(SECCLASS_NETIF, NETIF__EGRESS, "egress") > > S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, > > "connectto") S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, > > "newconn") S_(SECCLASS_UNIX_STREAM_SOCKET, > > UNIX_STREAM_SOCKET__ACCEPTFROM, "acceptfrom") @@ -159,3 +163,4 @@ > > S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind") > > S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect") > > S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero") > > + S_(SECCLASS_PEER, PEER__RECV, "recv") > > diff --git a/security/selinux/include/av_permissions.h > > b/security/selinux/include/av_permissions.h index eda89a2..c2b5bb2 100644 > > --- a/security/selinux/include/av_permissions.h > > +++ b/security/selinux/include/av_permissions.h > > @@ -292,6 +292,8 @@ > > #define NODE__ENFORCE_DEST0x0040UL > > #define NODE__DCCP_RECV 0x0080UL > > #define NODE__DCCP_SEND 0x0100UL > > +#define NODE__RECVFROM0x0200UL > > +#define NODE__SENDTO 0x0400UL > > #define NETIF__TCP_RECV 0x0001UL > > #define NETIF__TCP_SEND 0x0002UL > > #define NETIF__UDP_RECV 0x0004UL > > @@ -300,6 +302,8 @@ > > #define NETIF__RAWIP_SEND 0x0020UL > > #define NETIF__DCCP_RECV 0x0040UL > > #define NETIF__DCCP_SEND 0x0080UL > > +#define NETIF__INGRESS0x0100UL > > +#define NETIF__EGRESS 0x0200UL > > #define NETLINK_SOCKET__IOCTL 0x0001UL > > #define NETLINK_SOCKET__READ 0x0002UL > > #define NETLINK_SOCKET__WRITE 0x0004UL > > @@ -824,3 +828,4 @@ > > #define DCCP_SOCKET__NODE_BIND0x0040UL > > #define DCCP_SOCKET__NAME_CONNECT 0x0080UL > > #define MEMPROTECT__MMAP_ZERO 0x0001UL > > +#define PEER__RECV0x0001UL > > diff --git a/security/selinux/include/class_to_string.h > > b/security/selinux/include/class_to_string.h index e77de0e..b1b0d1d