Skip to contentSkip to conversation

Passing sec info to security modules when mounting an FS

DISCUSSION Eric Paris 3 participants 5 messages Jun 1, 2007 – Jun 6, 2007

Subsystems (3)
lore
Share & tools
lore

Eric Paris

author
#0 lore raw

A while back I posted a (ugly) patch trying to address a quirk found dealing with NFS and it's use of binary mount data.

http://marc.info/?l=linux-nfs&m=117856053112297&w=2

The answer was LSM modules/SELinux 'stop trying to read NFS's binary mount data.' So now I'm working on a real long term solution to the problem.

A two second overview of how this work now. With binary mount data, SELinux checks if the FS is NFS and if so inside try_context_mount() it casts the data to a nfs_mount_data and then grabs the security context from the data->context field added in version 6 of the nfs_mount_data. Its being doing that for quite some time now. For any FS which has binary mount data other than NFS it is impossible to pass security relevant information to the SELinux. For text mount options selinux walks the string, copies all of the relevant options (context=, fscontext=, defcontext=, rootcontext=) to a new page and then inside try_context_mount() uses those options.

Since everyone seemed to agree that having selinux grab the context out of the binary data was the wrong way to do things it appears that filesystems like NFS, which have binary mount data, are going to need a way to pass the security information contained in that mount data through the VFS to get it to the LSM hooks. I figure we can add a new vfs_kern_mount_secdata() which takes as a argument a string which contains all of the relevant security information. This string can then be passed right on down into the security modules and we can eliminate the NFS specific handling of the mount data in the selinux code.

The first problem with this right now is that the SELinux parser is expecting to get full mount options like context=user_u:role_r:type_t but the NFS code (somewhere I haven't figure out where yet) is manipulating the security string and taking the context=blah and stripping the first part of the string and only storing the part after the =. Which means that now something is going to have to change how the security options are being handled. I can see this being done a couple of places

?the nfs code - can just store the full text string it got in userspace and pass it along. Other binary mount data FS's could do the same thing. (I think this is the best option)

?the nfs code - can just append context= onto the front of the string before it calls into the new vfs_kern_mount_secdata() function, seems like this is not the place to add some selinux specific text manipulation, but then again, nfs decided to pull that part of the string off, why can't it put it back?

?the vfs to a new LSM hook - create some new hook which verifys the data and can manipulate it if needed before it is passed to the real LSM hook? (ok this is a terrible idea)

?extra flags being passed down to the original security_sb_kern_mount hook - if we pass extra flags down the security_sb_kern_mount to say this came from a binary mount then the selinux code could deal with all of the special casing itself.

?no extra flags and selinux code can just assume what is meant when it gets a string without one of the tokens it recognizes. Right now we catch those errors and bomb out, but I haven't ever seen the printk...

Personally I think the 'fix' should be to store the full string in the data->context field of the nfs data instead of making the NFS chain parse and manipulate the string. If others in the NFS world agree to this solution can you give me pointers to where the context= part of the
mount options got pulled off? Is that in userspace?

It also is a bit of a change in meaning for the ->context field. It no longer would be just a selinux context and would instead be a 'security string' which could contain all of the possible options someday and would get parsed correctly.

I also heard that NFS was going to go to a text mount option in the future and maybe for such a corner case of a problem (remember that link way back at the top) we could just ignore all of this until that happens. If so I think all of the problem would go away since selinux can just find its options from the text string like every other FS already does. In the meantime maybe people would be agreeable to a nasty hack inside the SELinux code (something like changing the nfs specific check in try_context_mount to (d->version < NFS_MOUNT_VERSION) && (d->version < 0xc00000000) to get the same result as my previous hack in the other patch but realize that d->version might actually be a pointer to a kernel data structure rather than to a version field)

So what is the right longterm solution? Add a new vfs function which takes a security string and change NFS to keep the whole string? Wait the problem out and go with a hack? Do something I haven't though of?

-Eric

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

#1 lore raw
Quoted 39 lines · Eric Paris

A while back I posted a (ugly) patch trying to address a quirk found dealing with NFS and it's use of binary mount data.

http://marc.info/?l=linux-nfs&m=117856053112297&w=2

The answer was LSM modules/SELinux 'stop trying to read NFS's binary mount data.' So now I'm working on a real long term solution to the problem.

A two second overview of how this work now. With binary mount data, SELinux checks if the FS is NFS and if so inside try_context_mount() it casts the data to a nfs_mount_data and then grabs the security context from the data->context field added in version 6 of the nfs_mount_data. Its being doing that for quite some time now. For any FS which has binary mount data other than NFS it is impossible to pass security relevant information to the SELinux. For text mount options selinux walks the string, copies all of the relevant options (context=, fscontext=, defcontext=, rootcontext=) to a new page and then inside try_context_mount() uses those options.

Since everyone seemed to agree that having selinux grab the context out of the binary data was the wrong way to do things it appears that filesystems like NFS, which have binary mount data, are going to need a way to pass the security information contained in that mount data through the VFS to get it to the LSM hooks. I figure we can add a new vfs_kern_mount_secdata() which takes as a argument a string which contains all of the relevant security information. This string can then be passed right on down into the security modules and we can eliminate the NFS specific handling of the mount data in the selinux code.

The first problem with this right now is that the SELinux parser is expecting to get full mount options like context=user_u:role_r:type_t but the NFS code (somewhere I haven't figure out where yet) is manipulating the security string and taking the context=blah and stripping the first part of the string and only storing the part after the =. Which means that now something is going to have to change how the security options are being handled. I can see this being done a couple of places

Quoted 3 lines

?the nfs code - can just store the full text string it got in userspace and pass it along. Other binary mount data FS's could do the same thing. (I think this is the best option)

I don't think that makes much sense from the filesystem point of view - the filesystem owns the options and parses them, passing only a flag to indicate the type of option (context, fscontext, defcontext) and the option value, not the prefixes, to the security module.

I'd expect it to be a direct call from the nfs option parsing code to a security function (which internally would call the security module's operation); no need to call back into the vfs there.

Quoted 53 lines

?the nfs code - can just append context= onto the front of the string before it calls into the new vfs_kern_mount_secdata() function, seems like this is not the place to add some selinux specific text manipulation, but then again, nfs decided to pull that part of the string off, why can't it put it back?

?the vfs to a new LSM hook - create some new hook which verifys the data and can manipulate it if needed before it is passed to the real LSM hook? (ok this is a terrible idea)

?extra flags being passed down to the original security_sb_kern_mount hook - if we pass extra flags down the security_sb_kern_mount to say this came from a binary mount then the selinux code could deal with all of the special casing itself.

?no extra flags and selinux code can just assume what is meant when it gets a string without one of the tokens it recognizes. Right now we catch those errors and bomb out, but I haven't ever seen the printk...

Personally I think the 'fix' should be to store the full string in the data->context field of the nfs data instead of making the NFS chain parse and manipulate the string. If others in the NFS world agree to this solution can you give me pointers to where the context= part of the
mount options got pulled off? Is that in userspace?

It also is a bit of a change in meaning for the ->context field. It no longer would be just a selinux context and would instead be a 'security string' which could contain all of the possible options someday and would get parsed correctly.

I also heard that NFS was going to go to a text mount option in the future and maybe for such a corner case of a problem (remember that link way back at the top) we could just ignore all of this until that happens. If so I think all of the problem would go away since selinux can just find its options from the text string like every other FS already does. In the meantime maybe people would be agreeable to a nasty hack inside the SELinux code (something like changing the nfs specific check in try_context_mount to (d->version < NFS_MOUNT_VERSION) && (d->version < 0xc00000000) to get the same result as my previous hack in the other patch but realize that d->version might actually be a pointer to a kernel data structure rather than to a version field)

So what is the right longterm solution? Add a new vfs function which takes a security string and change NFS to keep the whole string? Wait the problem out and go with a hack? Do something I haven't though of?

-Eric

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

Signature · 8 lines
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to [email protected] with
the words "unsubscribe selinux" without quotes as the message.
author
#2 lore raw
Quoted 6 lines · Stephen Smalley
Quoted 3 lines · Eric Paris

?the nfs code - can just store the full text string it got in userspace and pass it along. Other binary mount data FS's could do the same thing. (I think this is the best option)

Quoted 8 lines

I don't think that makes much sense from the filesystem point of view - the filesystem owns the options and parses them, passing only a flag to indicate the type of option (context, fscontext, defcontext) and the option value, not the prefixes, to the security module.

I'd expect it to be a direct call from the nfs option parsing code to a security function (which internally would call the security module's operation); no need to call back into the vfs there.

So it sounded good, tried to start coding the interface but couldn't think how to keep security module specific information out of the FS. SELinux in particular can grok 4 mount options,

fscontext=
context=
rootcontext=
defcontext=

NFS at the moment can only grok 1 of those 4 (far and away the most common) context= but I want the interface to be generic right? Lets say we were to create a new security function:

security_set_mount_option(struct *sb, char *option, int flag)

where the value of flag tells you what the information in *option is supposed to be setting. Immediately after the vfs_kern_mount call a FS which uses binary mount options could call into this new function thus avoiding the bad NFS specific code in the SELinux security module.

The problem is that the FS needs to now have security module specific knowledge in order to know how to pass the flag telling the security module what it is trying to set. We just moved NFS specific knowledge outside of the security module and put security module specific knowledge into the FS. What is SELinux isn't the security module? The meaning of 'flags' for SELinux would be which of those 4 above options they want to set. Now NFS has to know if selinux is being used or some other unknown security module which needs a different set of flag meanings. Where does this get worked out? In the text mount data the security code does all the parsing, so the FS doesn't need to know what the security module does or does not understand, although it seems like people don't think that's the right thing even for the text options case.

I'd be perfectly happy coding this with a hard coded value for the flag in NFS code and have that set the context=. Honestly right now it looks like nfs is going to be the only user and i certainly don't expect nfs to expand the binary data to support the other rarely used SELinux options. But it seems like a problem to me when the FS needs to understand all of the options for all of the possible security module needs (even if right now SELinux is the only security module I know of using this sort of thing....)

Any comments?

-Eric

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

#3 lore raw
Quoted 59 lines · Eric Paris
Quoted 6 lines · Stephen Smalley
Quoted 3 lines · Eric Paris

?the nfs code - can just store the full text string it got in userspace and pass it along. Other binary mount data FS's could do the same thing. (I think this is the best option)

Quoted 8 lines

I don't think that makes much sense from the filesystem point of view - the filesystem owns the options and parses them, passing only a flag to indicate the type of option (context, fscontext, defcontext) and the option value, not the prefixes, to the security module.

I'd expect it to be a direct call from the nfs option parsing code to a security function (which internally would call the security module's operation); no need to call back into the vfs there.

So it sounded good, tried to start coding the interface but couldn't think how to keep security module specific information out of the FS. SELinux in particular can grok 4 mount options,

fscontext=
context=
rootcontext=
defcontext=

NFS at the moment can only grok 1 of those 4 (far and away the most common) context= but I want the interface to be generic right? Lets say we were to create a new security function:

security_set_mount_option(struct *sb, char *option, int flag)

where the value of flag tells you what the information in *option is supposed to be setting. Immediately after the vfs_kern_mount call a FS which uses binary mount options could call into this new function thus avoiding the bad NFS specific code in the SELinux security module.

The problem is that the FS needs to now have security module specific knowledge in order to know how to pass the flag telling the security module what it is trying to set. We just moved NFS specific knowledge outside of the security module and put security module specific knowledge into the FS. What is SELinux isn't the security module? The meaning of 'flags' for SELinux would be which of those 4 above options they want to set. Now NFS has to know if selinux is being used or some other unknown security module which needs a different set of flag meanings. Where does this get worked out? In the text mount data the security code does all the parsing, so the FS doesn't need to know what the security module does or does not understand, although it seems like people don't think that's the right thing even for the text options case.

I'd be perfectly happy coding this with a hard coded value for the flag in NFS code and have that set the context=. Honestly right now it looks like nfs is going to be the only user and i certainly don't expect nfs to expand the binary data to support the other rarely used SELinux options. But it seems like a problem to me when the FS needs to understand all of the options for all of the possible security module needs (even if right now SELinux is the only security module I know of using this sort of thing....)

Quoted 1 line

Any comments?

As I understand it, the filesystem owns the options, not the security module, so the filesystem has to know them all. So yes, you'd just define a flag for the context option and use that one for context=. The dummy module can then implement the security_set_mount_option() hook by always returning -EINVAL so that it will reject any attempts to use that option, and any other security modules can do likewise or can do so selectively depending on whether they support the flag in question.

Although that hook should likely take an array so that you can pass all of the security-related options as a single call, as they might need to be considered together.

Signature · 8 lines
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to [email protected] with
the words "unsubscribe selinux" without quotes as the message.
#4 lore raw
In reply to Eric Paris
Quoted 73 lines · Eric Paris

A while back I posted a (ugly) patch trying to address a quirk found dealing with NFS and it's use of binary mount data.

http://marc.info/?l=linux-nfs&m=117856053112297&w=2

The answer was LSM modules/SELinux 'stop trying to read NFS's binary mount data.' So now I'm working on a real long term solution to the problem.

A two second overview of how this work now. With binary mount data, SELinux checks if the FS is NFS and if so inside try_context_mount() it casts the data to a nfs_mount_data and then grabs the security context from the data->context field added in version 6 of the nfs_mount_data. Its being doing that for quite some time now. For any FS which has binary mount data other than NFS it is impossible to pass security relevant information to the SELinux. For text mount options selinux walks the string, copies all of the relevant options (context=, fscontext=, defcontext=, rootcontext=) to a new page and then inside try_context_mount() uses those options.

Since everyone seemed to agree that having selinux grab the context out of the binary data was the wrong way to do things it appears that filesystems like NFS, which have binary mount data, are going to need a way to pass the security information contained in that mount data through the VFS to get it to the LSM hooks. I figure we can add a new vfs_kern_mount_secdata() which takes as a argument a string which contains all of the relevant security information. This string can then be passed right on down into the security modules and we can eliminate the NFS specific handling of the mount data in the selinux code.

The first problem with this right now is that the SELinux parser is expecting to get full mount options like context=user_u:role_r:type_t but the NFS code (somewhere I haven't figure out where yet) is manipulating the security string and taking the context=blah and stripping the first part of the string and only storing the part after the =. Which means that now something is going to have to change how the security options are being handled. I can see this being done a couple of places

?the nfs code - can just store the full text string it got in userspace and pass it along. Other binary mount data FS's could do the same thing. (I think this is the best option)

?the nfs code - can just append context= onto the front of the string before it calls into the new vfs_kern_mount_secdata() function, seems like this is not the place to add some selinux specific text manipulation, but then again, nfs decided to pull that part of the string off, why can't it put it back?

?the vfs to a new LSM hook - create some new hook which verifys the data and can manipulate it if needed before it is passed to the real LSM hook? (ok this is a terrible idea)

?extra flags being passed down to the original security_sb_kern_mount hook - if we pass extra flags down the security_sb_kern_mount to say this came from a binary mount then the selinux code could deal with all of the special casing itself.

?no extra flags and selinux code can just assume what is meant when it gets a string without one of the tokens it recognizes. Right now we catch those errors and bomb out, but I haven't ever seen the printk...

Personally I think the 'fix' should be to store the full string in the data->context field of the nfs data instead of making the NFS chain parse and manipulate the string. If others in the NFS world agree to this solution can you give me pointers to where the context= part of the
mount options got pulled off? Is that in userspace?

It also is a bit of a change in meaning for the ->context field. It no longer would be just a selinux context and would instead be a 'security string' which could contain all of the possible options someday and would get parsed correctly.

Quoted 11 lines

I also heard that NFS was going to go to a text mount option in the future and maybe for such a corner case of a problem (remember that link way back at the top) we could just ignore all of this until that happens. If so I think all of the problem would go away since selinux can just find its options from the text string like every other FS already does. In the meantime maybe people would be agreeable to a nasty hack inside the SELinux code (something like changing the nfs specific check in try_context_mount to (d->version < NFS_MOUNT_VERSION) && (d->version < 0xc00000000) to get the same result as my previous hack in the other patch but realize that d->version might actually be a pointer to a kernel data structure rather than to a version field)

No. The change to a text based mount option changes _nothing_. Firstly, we still have to keep a backward-compatibility layer in order to deal with old copies of the "mount" utility. Secondly, I expect that we will still be using binary interfaces when doing internal submounts such as when we cross over a remote filesystem boundary and/or when we encounter an NFSv4 referral.

The correct thing here is to allow NFS to parse its own mount options, then have the parser call a security function with the context string and the vfsmount (or superblock) as the only arguments.
If selinux requires the string to be stored then it should be responsible for managing that memory (i.e. for calling kstrdup() and kfree() at mount/umount).

Cheers
Trond

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs