Re: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
On 2007-06-25T17:14:11, Pavel Machek [EMAIL PROTECTED] wrote: Actually, I surprised Lars a lot by telling him ln /etc/shadow /tmp/ allows any user to make AA ineffective on large part of systems -- in internal discussion. (It is not actually a _bug_, but it is certainly unexpected). Pavel, no, you did not. You _did_ surprise me by misquoting me so badly, though. I agreed that actions by not mediated processes can interfere with mediated processes. That is a given. So you do not give them free access to a world writable directory. Regards, Lars -- Teamlead Kernel, SuSE Labs, Research and Development SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg) Experience is the name everyone gives to their mistakes. -- Oscar Wilde - 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 try #2] security: Convert LSM into a static interface
Quoting Kyle Moffett ([EMAIL PROTECTED]): On Jun 25, 2007, at 16:37:58, Andreas Gruenbacher wrote: On Monday 25 June 2007 06:33, James Morris wrote: Convert LSM into a static interface, as the ability to unload a security module is not required by in-tree users and potentially complicates the overall security architecture. It's useful for some LSMs to be modular, and LSMs which are y/n options won't have any security architecture issues with unloading at all. The mere fact that SELinux cannot be built as a module is a rather weak argument for disabling LSM modules as a whole, so please don't. Here are a few questions for you: 1) What do you expect to happen to all the megs of security data when you rmmod selinux? Read the sentence right above yours again. Noone is saying we should be able to rmmod selinux. Do you maintain a massive linked list of security data (with all the locking and performance problems) so that you can iterate over it calling kfree()? What synchronization primitive do we have right now which could safely stop all CPUs outside of security calls while we NULL out and free security data and disable security operations? Don't say software suspend and process freezer, since those have whole order-of-magnitude- complexity problems of their own (and don't always work right either). 2) When you modprobe my_custom_security_module, how exactly do you expect that all the processes, files, shared memory segments, file descriptors, sockets, SYSV mutexes, packets, etc will get appropriate security pointers? Those don't all need labels for capabilities, for instance. This question is as wrong as the last one. This isn't even solvable the same way the rmmod problem is, since most of that isn't even accessible without iterating over the ENTIRE dcache, icache, every process, every process' file-descriptors, every socket, every unix socket, every anonymous socket, every SYSV shm object, every currently-in- process packet. 3) This sounds suspiciously like The mere fact that the Linux-2.6-VM cannot be built as a module is a rather weak argument for disabling VFS modules as a whole. We don't do pluggable No, your argument sounds like my fs can't be a module so neither should any. fundamental infrastructure in Linux. If it's fundamental infrastructure then you eliminate as many differences as possible and leave the rest to CONFIG options (or delete it entirely). So... Do you have a proposal for solving those rather fundamental design gotchas? If so, I'm sure everybody here would love to see your patch; though maybe not if it's a 32MB patch-zilla-of-doom (AKPM beware, the merge-conflict-from-hell is on its way). On the other hand, if you accept that these problems basically can't be solved and we make things static and rip out a bunch of code, we can probably improve our performance under larger security models (like SELinux/ AppArmor/TOMOYO/MagicSecurityFlavorOfTheWeek(TM)) by a percent or two. Cheers, Kyle Moffett - 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 - 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 try #2] security: Convert LSM into a static interface
Quoting Adrian Bunk ([EMAIL PROTECTED]): On Mon, Jun 25, 2007 at 10:57:31PM -0500, Serge E. Hallyn wrote: Quoting James Morris ([EMAIL PROTECTED]): On Mon, 25 Jun 2007, Andreas Gruenbacher wrote: It's useful for some LSMs to be modular, and LSMs which are y/n options won't have any security architecture issues with unloading at all. Which LSMs? Upstream, there are SELinux and capabilty, and they're not safe as loadable modules. The mere fact that SELinux cannot be built as a module is a rather weak argument for disabling LSM modules as a whole, so please don't. That's not the argument. Please review the thread. The argument is 'abuse', right? Abuse is defined as using the LSM hooks for non-security applications, right? It seems to me that the community is doing a good job of discouraging such abuse - by redirecting the wrong-doers to implement proper upstream solutions, i.e. taskstats, the audit subsystem, etc. Such encouragement seems a far better response than taking away freedoms and flexibility from everyone. We are not living in a world where everyone had good intentions... Oh no, i took a wrong turn somewhere :) For _some_ wrong-doers your approach works. But how do you convince the wrong-doers who do things like putting MODULE_LICENSE(GPL) into their binary-only modules and who ignore you and get away because noone sues them? Do these really exist? Maybe noone sues them because noone knows who they are... But - note that you've changed completely the meaning of 'abuse'. So mine was wrong? The spirit of the GPLv2 is to defend the freedom of the software (different from the spirit of the BSD licence), and considering that there aren't many people defending the GPLv2 copyright of the Linux kernel at court against abusers, making it harder for people to do the abuse might not be the worst choice... Well, but you seem to be saying that the license means squat, and resorting to making things inconvenient rather than illegal. Now I guess if it really is accepted that that's the way it should be, then this patch will go in. -serge - 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 try #2] security: Convert LSM into a static interface
On Tue, Jun 26, 2007 at 09:06:44AM -0500, Serge E. Hallyn wrote: Quoting Adrian Bunk ([EMAIL PROTECTED]): On Mon, Jun 25, 2007 at 10:57:31PM -0500, Serge E. Hallyn wrote: Quoting James Morris ([EMAIL PROTECTED]): On Mon, 25 Jun 2007, Andreas Gruenbacher wrote: It's useful for some LSMs to be modular, and LSMs which are y/n options won't have any security architecture issues with unloading at all. Which LSMs? Upstream, there are SELinux and capabilty, and they're not safe as loadable modules. The mere fact that SELinux cannot be built as a module is a rather weak argument for disabling LSM modules as a whole, so please don't. That's not the argument. Please review the thread. The argument is 'abuse', right? Abuse is defined as using the LSM hooks for non-security applications, right? It seems to me that the community is doing a good job of discouraging such abuse - by redirecting the wrong-doers to implement proper upstream solutions, i.e. taskstats, the audit subsystem, etc. Such encouragement seems a far better response than taking away freedoms and flexibility from everyone. We are not living in a world where everyone had good intentions... Oh no, i took a wrong turn somewhere :) For _some_ wrong-doers your approach works. But how do you convince the wrong-doers who do things like putting MODULE_LICENSE(GPL) into their binary-only modules and who ignore you and get away because noone sues them? Do these really exist? Maybe noone sues them because noone knows who they are... http://lwn.net/Articles/82306/ But - note that you've changed completely the meaning of 'abuse'. So mine was wrong? Technical and legal abuse are related. For GPL'ed modules you might assume good faith and get the authors to do things in a proper way. Authors of legally questionable modules that cheat in many ways are quite a different issue. The spirit of the GPLv2 is to defend the freedom of the software (different from the spirit of the BSD licence), and considering that there aren't many people defending the GPLv2 copyright of the Linux kernel at court against abusers, making it harder for people to do the abuse might not be the worst choice... Well, but you seem to be saying that the license means squat, and resorting to making things inconvenient rather than illegal. No, the point is that there's no reason for making illegal things convenient. I'm not talking about removing things that are used inside the kernel, but what you call freedom can also be called hooks for possible abuse. Additionally, it both makes the kernel bigger for everyone and requires proper handling of loading/unloading in the security architecture. Now I guess if it really is accepted that that's the way it should be, then this patch will go in. -serge cu Adrian -- Is there not promise of rain? Ling Tan asked suddenly out of the darkness. There had been need of rain for many days. Only a promise, Lao Er said. Pearl S. Buck - Dragon Seed - 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: What kind of feature does New LSM security model need?
--- Kazuki Omo(Company) [EMAIL PROTECTED] wrote: Folks, May I ask some foolish questions? So long as you're not afraid of foolish answers. I just want to make sure what do we need if we want to put new security module(which is using LSM) in mainline. 1. Does it have to provide complete MAC which Casey Schaufler explained in below mail? http://marc.info/?l=linux-kernelm=118252843017261w=2 No. Your mechanism can be descretionary if you like. It can be based on user IDs, phase of the moon, or any other scheme you like. The arguments you've seen claiming that a module should not go upstream because the mechanism is incomplete go against the spirit of the LSM and should be ignored. 2. Does it have to provide any solution which SELinux can't cover? HeeHee. There do appear to be some SELinux zealots out there, don't there? No. Overlap between your module and SELinux is irrelevent. SELinux is one security scheme, and it is intended to cover all possible cases. 3. Do we have to proof the new security module can't implement as policy on SELinux? Well, it wouldn't hurt. But look at what happened in the AppArmor argument. First, AppArmor claimed to do something that SELinux couldn't do. The SELinux Zealot response was that SELinux could do that. The AppArmor crowd requested demonstration. The Zealots spent a couple days hacking something up, and presented it. This bit of hackery was heavily criticized from several fronts. The Zealots then used this criticizm to say that this proved that the problem was with the underlying premise of AppArmor. Don't expect it to be easy and don't expect all the arguments to follow traditional rules of debate. Finally, if you prove that you have something truely unique that SELinux can't do, expect to be told that no one would want that anyway. 4. Does it have to provide complete security feature from beginning? Can we implement just small features to mainline and develop new features in same time? Release early and often, but come in with enough so that it's clear what you intend to do, why what you have is special, and what impact it might have on the rest of the system. AppArmor's big problem is the changes required to the vfs layer. It would be very difficult to get the natives so worked up about AppArmor if it was an LSM that required no external changes. 5. Does it have to have any Security model which documented/evaluated in academic conference? I certainly hope not. One of the intentions of LSM, at least early on, was to encourage new and inovative models. I can understand how it might seem otherwise given some of the recent debates. I saw LSM-ML past 1 year and sometime I saw You should try and get your code into mainline. But, anytime many people were discussing about above points and I think nobody put anything in mainline (Now I'm checking 2.6.21 kernel and I couldn't find any security module except Default Linux Capabilities, Root Plug, and SELinux). That's correct. As your questions lead the reader to summize, there is a faction that does not want any more LSMs. Some members of the community would be happy for LSM to be abandoned and SELinux adopted as the Linux security infrastructure. These people often point to the fact that there are no other LSMs to back their position. They also work to make the notion of presenting an LSM for consideration frightening, and as your message here indicates, have had no small success. Not everyone associated with SELinux exhibits these behaviors, and there is definitly anti-SELinux zeal in the community, too. No one gets defensive if they've never been attacked, after all. My suggestion? Make sure your LSM is so clean it squeeks. Provide as much information about what it does and why it's good as you can. Can SELinux do the same thing? Maybe, but so what? Let the zealots prove it. Either way thank them for their input and move on. It may take years to get your LSM upstream, it certainly took SELinux a while, and the version that got in bears very little resemblence to what they first proposed. Best of luck, and thank you for making the effort. Casey Schaufler [EMAIL PROTECTED] - 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 try #2] security: Convert LSM into a static interface
On Tue, Jun 26, 2007 at 09:06:44AM -0500, Serge E. Hallyn wrote: Quoting Adrian Bunk ([EMAIL PROTECTED]): On Mon, Jun 25, 2007 at 10:57:31PM -0500, Serge E. Hallyn wrote: Quoting James Morris ([EMAIL PROTECTED]): On Mon, 25 Jun 2007, Andreas Gruenbacher wrote: It's useful for some LSMs to be modular, and LSMs which are y/n options won't have any security architecture issues with unloading at all. Which LSMs? Upstream, there are SELinux and capabilty, and they're not safe as loadable modules. The mere fact that SELinux cannot be built as a module is a rather weak argument for disabling LSM modules as a whole, so please don't. That's not the argument. Please review the thread. The argument is 'abuse', right? Abuse is defined as using the LSM hooks for non-security applications, right? It seems to me that the community is doing a good job of discouraging such abuse - by redirecting the wrong-doers to implement proper upstream solutions, i.e. taskstats, the audit subsystem, etc. Such encouragement seems a far better response than taking away freedoms and flexibility from everyone. We are not living in a world where everyone had good intentions... Oh no, i took a wrong turn somewhere :) For _some_ wrong-doers your approach works. But how do you convince the wrong-doers who do things like putting MODULE_LICENSE(GPL) into their binary-only modules and who ignore you and get away because noone sues them? Do these really exist? Yes they do. Maybe noone sues them because noone knows who they are... Maybe no one knows because the people doing the legal action against them are trying to be nice and do it quietly. And legal action takes time, it is quite slow going unfortunatly. Heck, I've seen code that is even properly licensed under the GPL abuse this security layer for things it was not ment to do at all, and that stuff comes from _very_ big companies that really should know better... So I agree that we should unexport it. It will make people who want to abuse the interface at least think twice about it. thanks, greg I want to mark structures read-only k-h - 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 try #2] security: Convert LSM into a static interface
Quoting Greg KH ([EMAIL PROTECTED]): On Tue, Jun 26, 2007 at 09:06:44AM -0500, Serge E. Hallyn wrote: Quoting Adrian Bunk ([EMAIL PROTECTED]): On Mon, Jun 25, 2007 at 10:57:31PM -0500, Serge E. Hallyn wrote: Quoting James Morris ([EMAIL PROTECTED]): On Mon, 25 Jun 2007, Andreas Gruenbacher wrote: It's useful for some LSMs to be modular, and LSMs which are y/n options won't have any security architecture issues with unloading at all. Which LSMs? Upstream, there are SELinux and capabilty, and they're not safe as loadable modules. The mere fact that SELinux cannot be built as a module is a rather weak argument for disabling LSM modules as a whole, so please don't. That's not the argument. Please review the thread. The argument is 'abuse', right? Abuse is defined as using the LSM hooks for non-security applications, right? It seems to me that the community is doing a good job of discouraging such abuse - by redirecting the wrong-doers to implement proper upstream solutions, i.e. taskstats, the audit subsystem, etc. Such encouragement seems a far better response than taking away freedoms and flexibility from everyone. We are not living in a world where everyone had good intentions... Oh no, i took a wrong turn somewhere :) For _some_ wrong-doers your approach works. But how do you convince the wrong-doers who do things like putting MODULE_LICENSE(GPL) into their binary-only modules and who ignore you and get away because noone sues them? Do these really exist? Yes they do. Maybe noone sues them because noone knows who they are... Maybe no one knows because the people doing the legal action against them are trying to be nice and do it quietly. So they're being nice to the violaters, and then clamping down on everyone... And legal action takes time, it is quite slow going unfortunatly. Heck, I've seen code that is even properly licensed under the GPL abuse this security layer for things it was not ment to do at all, and that stuff comes from _very_ big companies that really should know better... But that's back to the other type of 'abuse' which i was originally talking about, and which IMO is being well addressed through education. As for the others, I have no better suggestions. I wish I did. So I agree that we should unexport it. It will make people who want to abuse the interface at least think twice about it. And those who don't abuse it too. thanks, greg I want to mark structures read-only k-h And I know I'm not the one who's going to stop you... -serge - 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: [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching
Chris Wright wrote: * Chris Mason ([EMAIL PROTECTED]) wrote: I'm sure people there will have a different versions of events. The one part that was discussed was if pathname based security was useful, and a number of the people in the room (outside of novell) said it was. Now, it could be that nobody wanted to argue anymore, since most opinions had come out on one list or another by then. Indeed. The trouble is that's too high level compared with the actual implementation details. AA is stalled because it has failed to get VFS support for it's model. I don't see a nice way out unless it changes it's notion of policy language (globbing is the tough one) or gets traction to pass dentry/vfsmount all the way down. Paths are completely relevant for security, esp. when considering the parent dir and the leaf (as in forward lookup case). To do pathname-based access control in any way, the LSM must be able to obtain the pathname of an accessed object. The discussion should be about the best way for an LSM to obtain the pathname of an object being accessed. To find the pathname of the object, LSM needs the VFS mount point data. The VFS owns this information, so the question is the best way to convey it from VFS to relevant LSM hooks. We are agnostic about how to get that mount point data, but AFAICT saying that LSM can't see the mount point data at all is equivalent to rejecting pathname based access control entirely. Retroactively creating the full path is at the minimum ugly, and in the worst case can be insecure (yes AA has taken many measures to mitigate that insecurity). The reverse path construction has been criticized for being both broken and counter-intuitive. Our secure d_path patch fixes the broken part, it now securely reconstructs the path. The counter-intuitive is because forward construction of the pathname has unexpected costs, making the retroactive construction more attractive. AA folks: deal with the VFS issues that your patchset have in a palatable way (which does not include passing NULL when it's inconvenient to do otherwise). John Johansen posted a patch (written by Andreas Gruenbacher) that introduced a nameidata2 data structure to try to solve the conditional null passing problem, but it received no comment. A proper fix to this problem is clearly desirable, but it also is clearly a defect in NFS and fixing it is a lot of work; why does AA have to stay outside the kernel until NFS is fixed, when it can easily adapt to the problem until it is fixed properly? You've already missed an opportunity with Christoph's suggestions for changes in NFS. I know you've considered many alternative approaches and consistently hit dead ends. But please note, if you have coded yourself into a corner because of your policy language, that's your issue to solve, not ours. I think it is a little more fundamental than that. If you are going to do pathname based access control at all, you need access to sufficient information to compute the path name. Can we have a discussion about the best way to do that? Crispin -- Crispin Cowan, Ph.D. http://crispincowan.com/~crispin/ Director of Software Engineering http://novell.com AppArmor Chat: irc.oftc.net/#apparmor - 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
[AppArmor 00/44] AppArmor security module overview
This post contains patches to include the AppArmor application security framework, with request for inclusion into -mm for wider testing. These patches are currently against lkml but we will gladly rebase them against -mm so that they will apply cleanly. Any comments and feedback to improve implementation are appreciated. A second post dealing with the issue of passing NULL nameidata, will be posted to lkml for discussion. Changes since previous post: - remove custom pathname mangling - rework apparmor auditing to cleanup message formating and better use audit framework - change permission consistency checks from runtime to once at policy load - add change_profile feature and cleanup change_hat to use change_profile The patch series consists of five areas: (1) Pass struct vfsmount through to LSM hooks. (2) Fixes and improvements to __d_path(): (a) make it unambiguous and exclude unreachable paths from /proc/mounts, (b) make its result consistent in the face of remounts, (c) introduce d_namespace_path(), a variant of d_path that goes up to the namespace root instead of the chroot. (d) the behavior of d_path() and getcwd() remain unchanged, and there is no hidding of unreachable paths in /proc/mounts. The patches addressing these have been seperated from the AppArmor submission and will be introduced at a later date. Part (a) has been in the -mm tree for a while; this series includes an updated copy of the -mm patch. Parts (b) and (c) shouldn't be too controversial. (3) Be able to distinguish file descriptor access from access by name in LSM hooks. Applications expect different behavior from file descriptor accesses and accesses by name in some cases. We need to pass this information down the LSM hooks to allow AppArmor to tell which is which. (4) Convert the selinux sysctl pathname computation code into a standalone function. (5) The AppArmor LSM itself. (See below.) A tarball of the kernel patches, base user-space utilities, example profiles, and technical documentation (including a walk-through) are available at: http://forgeftp.novell.com//apparmor/LKML_Submission-June-07/ Explaining the AppArmor design in detail would take by far too much space here, so let me refer you to the technical documentation for that. Included is a low-level walk-through of the system and basic tools, and some examples. The manual pages included in the apparmor-parser package are worth a read as well. -- - 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
[AppArmor 03/44] Add a vfsmount parameter to notify_change()
The vfsmount parameter must be set appropriately for files visibile outside the kernel. Files that are only used in a filesystem (e.g., reiserfs xattr files) will have a NULL vfsmount. Signed-off-by: Tony Jones [EMAIL PROTECTED] Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] --- fs/attr.c |3 ++- fs/ecryptfs/inode.c |4 +++- fs/exec.c |3 ++- fs/fat/file.c |2 +- fs/hpfs/namei.c |2 +- fs/namei.c |3 ++- fs/nfsd/vfs.c |8 fs/open.c | 28 +++- fs/reiserfs/xattr.c |6 +++--- fs/sysfs/file.c |2 +- fs/utimes.c | 11 ++- include/linux/fs.h |6 +++--- mm/filemap.c|2 +- mm/tiny-shmem.c |2 +- 14 files changed, 45 insertions(+), 37 deletions(-) --- a/fs/attr.c +++ b/fs/attr.c @@ -100,7 +100,8 @@ int inode_setattr(struct inode * inode, } EXPORT_SYMBOL(inode_setattr); -int notify_change(struct dentry * dentry, struct iattr * attr) +int notify_change(struct dentry *dentry, struct vfsmount *mnt, + struct iattr *attr) { struct inode *inode = dentry-d_inode; mode_t mode; --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -870,12 +870,14 @@ static int ecryptfs_setattr(struct dentr { int rc = 0; struct dentry *lower_dentry; + struct vfsmount *lower_mnt; struct inode *inode; struct inode *lower_inode; struct ecryptfs_crypt_stat *crypt_stat; crypt_stat = ecryptfs_inode_to_private(dentry-d_inode)-crypt_stat; lower_dentry = ecryptfs_dentry_to_lower(dentry); + lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); inode = dentry-d_inode; lower_inode = ecryptfs_inode_to_lower(inode); if (ia-ia_valid ATTR_SIZE) { @@ -890,7 +892,7 @@ static int ecryptfs_setattr(struct dentr if (rc 0) goto out; } - rc = notify_change(lower_dentry, ia); + rc = notify_change(lower_dentry, lower_mnt, ia); out: fsstack_copy_attr_all(inode, lower_inode, NULL); return rc; --- a/fs/exec.c +++ b/fs/exec.c @@ -1565,7 +1565,8 @@ int do_coredump(long signr, int exit_cod goto close_fail; if (!file-f_op-write) goto close_fail; - if (!ispipe do_truncate(file-f_path.dentry, 0, 0, file) != 0) + if (!ispipe + do_truncate(file-f_path.dentry, file-f_path.mnt, 0, 0, file) != 0) goto close_fail; retval = binfmt-core_dump(signr, regs, file); --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -92,7 +92,7 @@ int fat_generic_ioctl(struct inode *inod } /* This MUST be done before doing anything irreversible... */ - err = notify_change(filp-f_path.dentry, ia); + err = notify_change(filp-f_path.dentry, filp-f_path.mnt, ia); if (err) goto up; --- a/fs/hpfs/namei.c +++ b/fs/hpfs/namei.c @@ -426,7 +426,7 @@ again: /*printk(HPFS: truncating file before delete.\n);*/ newattrs.ia_size = 0; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; - err = notify_change(dentry, newattrs); + err = notify_change(dentry, NULL, newattrs); put_write_access(inode); if (!err) goto again; --- a/fs/namei.c +++ b/fs/namei.c @@ -1598,7 +1598,8 @@ int may_open(struct nameidata *nd, int a if (!error) { DQUOT_INIT(inode); - error = do_truncate(dentry, 0, ATTR_MTIME|ATTR_CTIME, NULL); + error = do_truncate(dentry, nd-mnt, 0, + ATTR_MTIME|ATTR_CTIME, NULL); } put_write_access(inode); if (error) --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -358,7 +358,7 @@ nfsd_setattr(struct svc_rqst *rqstp, str err = nfserr_notsync; if (!check_guard || guardtime == inode-i_ctime.tv_sec) { fh_lock(fhp); - host_err = notify_change(dentry, iap); + host_err = notify_change(dentry, fhp-fh_export-ex_mnt, iap); err = nfserrno(host_err); fh_unlock(fhp); } @@ -893,13 +893,13 @@ out: return err; } -static void kill_suid(struct dentry *dentry) +static void kill_suid(struct dentry *dentry, struct vfsmount *mnt) { struct iattria; ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID; mutex_lock(dentry-d_inode-i_mutex); - notify_change(dentry, ia); + notify_change(dentry, mnt, ia); mutex_unlock(dentry-d_inode-i_mutex); } @@ -958,7 +958,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, s
[AppArmor 01/44] Pass struct vfsmount to the inode_create LSM hook
This is needed for computing pathnames in the AppArmor LSM. Signed-off-by: Tony Jones [EMAIL PROTECTED] Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] --- fs/namei.c |2 +- include/linux/security.h |9 ++--- security/dummy.c |2 +- security/selinux/hooks.c |3 ++- 4 files changed, 10 insertions(+), 6 deletions(-) --- a/fs/namei.c +++ b/fs/namei.c @@ -1521,7 +1521,7 @@ int vfs_create(struct inode *dir, struct return -EACCES; /* shouldn't it be ENOSYS? */ mode = S_IALLUGO; mode |= S_IFREG; - error = security_inode_create(dir, dentry, mode); + error = security_inode_create(dir, dentry, nd ? nd-mnt : NULL, mode); if (error) return error; DQUOT_INIT(dir); --- a/include/linux/security.h +++ b/include/linux/security.h @@ -283,6 +283,7 @@ struct request_sock; * Check permission to create a regular file. * @dir contains inode structure of the parent of the new file. * @dentry contains the dentry structure for the file to be created. + * @mnt is the vfsmount corresponding to @dentry (may be NULL). * @mode contains the file mode of the file to be created. * Return 0 if permission is granted. * @inode_link: @@ -1204,8 +1205,8 @@ struct security_operations { void (*inode_free_security) (struct inode *inode); int (*inode_init_security) (struct inode *inode, struct inode *dir, char **name, void **value, size_t *len); - int (*inode_create) (struct inode *dir, -struct dentry *dentry, int mode); + int (*inode_create) (struct inode *dir, struct dentry *dentry, +struct vfsmount *mnt, int mode); int (*inode_link) (struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry); int (*inode_unlink) (struct inode *dir, struct dentry *dentry); @@ -1611,11 +1612,12 @@ static inline int security_inode_init_se static inline int security_inode_create (struct inode *dir, struct dentry *dentry, +struct vfsmount *mnt, int mode) { if (unlikely (IS_PRIVATE (dir))) return 0; - return security_ops-inode_create (dir, dentry, mode); + return security_ops-inode_create (dir, dentry, mnt, mode); } static inline int security_inode_link (struct dentry *old_dentry, @@ -2338,6 +2340,7 @@ static inline int security_inode_init_se static inline int security_inode_create (struct inode *dir, struct dentry *dentry, +struct vfsmount *mnt, int mode) { return 0; --- a/security/dummy.c +++ b/security/dummy.c @@ -265,7 +265,7 @@ static int dummy_inode_init_security (st } static int dummy_inode_create (struct inode *inode, struct dentry *dentry, - int mask) + struct vfsmount *mnt, int mask) { return 0; } --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2176,7 +2176,8 @@ static int selinux_inode_init_security(s return 0; } -static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask) +static int selinux_inode_create(struct inode *dir, struct dentry *dentry, +struct vfsmount *mnt, int mask) { return may_create(dir, dentry, SECCLASS_FILE); } -- - 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
[AppArmor 06/44] Pass struct vfsmount to the inode_mkdir LSM hook
This is needed for computing pathnames in the AppArmor LSM. Signed-off-by: Tony Jones [EMAIL PROTECTED] Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] --- fs/namei.c |2 +- include/linux/security.h |8 ++-- security/dummy.c |2 +- security/selinux/hooks.c |3 ++- 4 files changed, 10 insertions(+), 5 deletions(-) --- a/fs/namei.c +++ b/fs/namei.c @@ -1946,7 +1946,7 @@ int vfs_mkdir(struct inode *dir, struct return -EPERM; mode = (S_IRWXUGO|S_ISVTX); - error = security_inode_mkdir(dir, dentry, mode); + error = security_inode_mkdir(dir, dentry, mnt, mode); if (error) return error; --- a/include/linux/security.h +++ b/include/linux/security.h @@ -308,6 +308,7 @@ struct request_sock; * associated with inode strcture @dir. * @dir containst the inode structure of parent of the directory to be created. * @dentry contains the dentry structure of new directory. + * @mnt is the vfsmount corresponding to @dentry (may be NULL). * @mode contains the mode of new directory. * Return 0 if permission is granted. * @inode_rmdir: @@ -1213,7 +1214,8 @@ struct security_operations { int (*inode_unlink) (struct inode *dir, struct dentry *dentry); int (*inode_symlink) (struct inode *dir, struct dentry *dentry, const char *old_name); - int (*inode_mkdir) (struct inode *dir, struct dentry *dentry, int mode); + int (*inode_mkdir) (struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mode); int (*inode_rmdir) (struct inode *dir, struct dentry *dentry); int (*inode_mknod) (struct inode *dir, struct dentry *dentry, int mode, dev_t dev); @@ -1650,11 +1652,12 @@ static inline int security_inode_symlink static inline int security_inode_mkdir (struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mode) { if (unlikely (IS_PRIVATE (dir))) return 0; - return security_ops-inode_mkdir (dir, dentry, mode); + return security_ops-inode_mkdir (dir, dentry, mnt, mode); } static inline int security_inode_rmdir (struct inode *dir, @@ -2371,6 +2374,7 @@ static inline int security_inode_symlink static inline int security_inode_mkdir (struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mode) { return 0; --- a/security/dummy.c +++ b/security/dummy.c @@ -288,7 +288,7 @@ static int dummy_inode_symlink (struct i } static int dummy_inode_mkdir (struct inode *inode, struct dentry *dentry, - int mask) + struct vfsmount *mnt, int mask) { return 0; } --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2207,7 +2207,8 @@ static int selinux_inode_symlink(struct return may_create(dir, dentry, SECCLASS_LNK_FILE); } -static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask) +static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, int mask) { return may_create(dir, dentry, SECCLASS_DIR); } -- - 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
[AppArmor 07/44] Add a struct vfsmount parameter to vfs_mknod()
The vfsmount will be passed down to the LSM hook so that LSMs can compute pathnames. Signed-off-by: Tony Jones [EMAIL PROTECTED] Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] --- fs/ecryptfs/inode.c |5 - fs/namei.c | 10 ++ fs/nfsd/vfs.c |3 ++- include/linux/fs.h |2 +- net/unix/af_unix.c |2 +- 5 files changed, 14 insertions(+), 8 deletions(-) --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -560,11 +560,14 @@ ecryptfs_mknod(struct inode *dir, struct { int rc; struct dentry *lower_dentry; + struct vfsmount *lower_mnt; struct dentry *lower_dir_dentry; lower_dentry = ecryptfs_dentry_to_lower(dentry); + lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); lower_dir_dentry = lock_parent(lower_dentry); - rc = vfs_mknod(lower_dir_dentry-d_inode, lower_dentry, mode, dev); + rc = vfs_mknod(lower_dir_dentry-d_inode, lower_dentry, lower_mnt, mode, + dev); if (rc || !lower_dentry-d_inode) goto out; rc = ecryptfs_interpose(lower_dentry, dentry, dir-i_sb, 0); --- a/fs/namei.c +++ b/fs/namei.c @@ -1855,7 +1855,8 @@ fail: } EXPORT_SYMBOL_GPL(lookup_create); -int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) +int vfs_mknod(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt, + int mode, dev_t dev) { int error = may_create(dir, dentry, NULL); @@ -1907,11 +1908,12 @@ asmlinkage long sys_mknodat(int dfd, con error = vfs_create(nd.dentry-d_inode,dentry,mode,nd); break; case S_IFCHR: case S_IFBLK: - error = vfs_mknod(nd.dentry-d_inode,dentry,mode, - new_decode_dev(dev)); + error = vfs_mknod(nd.dentry-d_inode, dentry, nd.mnt, + mode, new_decode_dev(dev)); break; case S_IFIFO: case S_IFSOCK: - error = vfs_mknod(nd.dentry-d_inode,dentry,mode,0); + error = vfs_mknod(nd.dentry-d_inode, dentry, nd.mnt, + mode, 0); break; case S_IFDIR: error = -EPERM; --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1194,7 +1194,8 @@ nfsd_create(struct svc_rqst *rqstp, stru case S_IFBLK: case S_IFIFO: case S_IFSOCK: - host_err = vfs_mknod(dirp, dchild, iap-ia_mode, rdev); + host_err = vfs_mknod(dirp, dchild, exp-ex_mnt, iap-ia_mode, +rdev); break; default: printk(nfsd: bad file type %o in nfsd_create\n, type); --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -994,7 +994,7 @@ extern void unlock_super(struct super_bl extern int vfs_permission(struct nameidata *, int); extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *); extern int vfs_mkdir(struct inode *, struct dentry *, struct vfsmount *, int); -extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t); +extern int vfs_mknod(struct inode *, struct dentry *, struct vfsmount *, int, dev_t); extern int vfs_symlink(struct inode *, struct dentry *, const char *, int); extern int vfs_link(struct dentry *, struct inode *, struct dentry *); extern int vfs_rmdir(struct inode *, struct dentry *); --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -807,7 +807,7 @@ static int unix_bind(struct socket *sock */ mode = S_IFSOCK | (SOCK_INODE(sock)-i_mode ~current-fs-umask); - err = vfs_mknod(nd.dentry-d_inode, dentry, mode, 0); + err = vfs_mknod(nd.dentry-d_inode, dentry, nd.mnt, mode, 0); if (err) goto out_mknod_dput; mutex_unlock(nd.dentry-d_inode-i_mutex); -- - 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
[AppArmor 10/44] Pass struct vfsmount to the inode_symlink LSM hook
This is needed for computing pathnames in the AppArmor LSM. Signed-off-by: Tony Jones [EMAIL PROTECTED] Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] --- fs/namei.c |2 +- include/linux/security.h |9 ++--- security/dummy.c |2 +- security/selinux/hooks.c |3 ++- 4 files changed, 10 insertions(+), 6 deletions(-) --- a/fs/namei.c +++ b/fs/namei.c @@ -2214,7 +2214,7 @@ int vfs_symlink(struct inode *dir, struc if (!dir-i_op || !dir-i_op-symlink) return -EPERM; - error = security_inode_symlink(dir, dentry, oldname); + error = security_inode_symlink(dir, dentry, mnt, oldname); if (error) return error; --- a/include/linux/security.h +++ b/include/linux/security.h @@ -301,6 +301,7 @@ struct request_sock; * Check the permission to create a symbolic link to a file. * @dir contains the inode structure of parent directory of the symbolic link. * @dentry contains the dentry structure of the symbolic link. + * @mnt is the vfsmount corresponding to @dentry (may be NULL). * @old_name contains the pathname of file. * Return 0 if permission is granted. * @inode_mkdir: @@ -1213,8 +1214,8 @@ struct security_operations { int (*inode_link) (struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry); int (*inode_unlink) (struct inode *dir, struct dentry *dentry); - int (*inode_symlink) (struct inode *dir, - struct dentry *dentry, const char *old_name); + int (*inode_symlink) (struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, const char *old_name); int (*inode_mkdir) (struct inode *dir, struct dentry *dentry, struct vfsmount *mnt, int mode); int (*inode_rmdir) (struct inode *dir, struct dentry *dentry); @@ -1644,11 +1645,12 @@ static inline int security_inode_unlink static inline int security_inode_symlink (struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, const char *old_name) { if (unlikely (IS_PRIVATE (dir))) return 0; - return security_ops-inode_symlink (dir, dentry, old_name); + return security_ops-inode_symlink (dir, dentry, mnt, old_name); } static inline int security_inode_mkdir (struct inode *dir, @@ -2369,6 +2371,7 @@ static inline int security_inode_unlink static inline int security_inode_symlink (struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt, const char *old_name) { return 0; --- a/security/dummy.c +++ b/security/dummy.c @@ -282,7 +282,7 @@ static int dummy_inode_unlink (struct in } static int dummy_inode_symlink (struct inode *inode, struct dentry *dentry, - const char *name) + struct vfsmount *mnt, const char *name) { return 0; } --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2202,7 +2202,8 @@ static int selinux_inode_unlink(struct i return may_link(dir, dentry, MAY_UNLINK); } -static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name) +static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, +struct vfsmount *mnt, const char *name) { return may_create(dir, dentry, SECCLASS_LNK_FILE); } -- - 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
[AppArmor 11/44] Pass struct vfsmount to the inode_readlink LSM hook
This is needed for computing pathnames in the AppArmor LSM. Signed-off-by: Tony Jones [EMAIL PROTECTED] Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] --- fs/stat.c|2 +- include/linux/security.h | 11 +++ security/dummy.c |2 +- security/selinux/hooks.c |2 +- 4 files changed, 10 insertions(+), 7 deletions(-) --- a/fs/stat.c +++ b/fs/stat.c @@ -306,7 +306,7 @@ asmlinkage long sys_readlinkat(int dfd, error = -EINVAL; if (inode-i_op inode-i_op-readlink) { - error = security_inode_readlink(nd.dentry); + error = security_inode_readlink(nd.dentry, nd.mnt); if (!error) { touch_atime(nd.mnt, nd.dentry); error = inode-i_op-readlink(nd.dentry, buf, bufsiz); --- a/include/linux/security.h +++ b/include/linux/security.h @@ -338,6 +338,7 @@ struct request_sock; * @inode_readlink: * Check the permission to read the symbolic link. * @dentry contains the dentry structure for the file link. + * @mnt is the vfsmount corresponding to @dentry (may be NULL). * Return 0 if permission is granted. * @inode_follow_link: * Check permission to follow a symbolic link when looking up a pathname. @@ -1223,7 +1224,7 @@ struct security_operations { struct vfsmount *mnt, int mode, dev_t dev); int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry); - int (*inode_readlink) (struct dentry *dentry); + int (*inode_readlink) (struct dentry *dentry, struct vfsmount *mnt); int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd); int (*inode_permission) (struct inode *inode, int mask, struct nameidata *nd); int (*inode_setattr) (struct dentry *dentry, struct vfsmount *mnt, @@ -1693,11 +1694,12 @@ static inline int security_inode_rename new_dir, new_dentry); } -static inline int security_inode_readlink (struct dentry *dentry) +static inline int security_inode_readlink (struct dentry *dentry, + struct vfsmount *mnt) { if (unlikely (IS_PRIVATE (dentry-d_inode))) return 0; - return security_ops-inode_readlink (dentry); + return security_ops-inode_readlink (dentry, mnt); } static inline int security_inode_follow_link (struct dentry *dentry, @@ -2407,7 +2409,8 @@ static inline int security_inode_rename return 0; } -static inline int security_inode_readlink (struct dentry *dentry) +static inline int security_inode_readlink (struct dentry *dentry, + struct vfsmount *mnt) { return 0; } --- a/security/dummy.c +++ b/security/dummy.c @@ -312,7 +312,7 @@ static int dummy_inode_rename (struct in return 0; } -static int dummy_inode_readlink (struct dentry *dentry) +static int dummy_inode_readlink (struct dentry *dentry, struct vfsmount *mnt) { return 0; } --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2237,7 +2237,7 @@ static int selinux_inode_rename(struct i return may_rename(old_inode, old_dentry, new_inode, new_dentry); } -static int selinux_inode_readlink(struct dentry *dentry) +static int selinux_inode_readlink(struct dentry *dentry, struct vfsmount *mnt) { return dentry_has_perm(current, NULL, dentry, FILE__READ); } -- - 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
[AppArmor 13/44] Pass the struct vfsmounts to the inode_link LSM hook
This is needed for computing pathnames in the AppArmor LSM. Signed-off-by: Tony Jones [EMAIL PROTECTED] Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] --- fs/namei.c |3 ++- include/linux/security.h | 18 +- security/dummy.c |6 -- security/selinux/hooks.c |9 +++-- 4 files changed, 26 insertions(+), 10 deletions(-) --- a/fs/namei.c +++ b/fs/namei.c @@ -2293,7 +2293,8 @@ int vfs_link(struct dentry *old_dentry, if (S_ISDIR(old_dentry-d_inode-i_mode)) return -EPERM; - error = security_inode_link(old_dentry, dir, new_dentry); + error = security_inode_link(old_dentry, old_mnt, dir, new_dentry, + new_mnt); if (error) return error; --- a/include/linux/security.h +++ b/include/linux/security.h @@ -289,8 +289,10 @@ struct request_sock; * @inode_link: * Check permission before creating a new hard link to a file. * @old_dentry contains the dentry structure for an existing link to the file. + * @old_mnt is the vfsmount corresponding to @old_dentry (may be NULL). * @dir contains the inode structure of the parent directory of the new link. * @new_dentry contains the dentry structure for the new link. + * @new_mnt is the vfsmount corresponding to @new_dentry (may be NULL). * Return 0 if permission is granted. * @inode_unlink: * Check the permission to remove a hard link to a file. @@ -1212,8 +1214,9 @@ struct security_operations { char **name, void **value, size_t *len); int (*inode_create) (struct inode *dir, struct dentry *dentry, struct vfsmount *mnt, int mode); - int (*inode_link) (struct dentry *old_dentry, - struct inode *dir, struct dentry *new_dentry); + int (*inode_link) (struct dentry *old_dentry, struct vfsmount *old_mnt, + struct inode *dir, struct dentry *new_dentry, + struct vfsmount *new_mnt); int (*inode_unlink) (struct inode *dir, struct dentry *dentry); int (*inode_symlink) (struct inode *dir, struct dentry *dentry, struct vfsmount *mnt, const char *old_name); @@ -1628,12 +1631,15 @@ static inline int security_inode_create } static inline int security_inode_link (struct dentry *old_dentry, + struct vfsmount *old_mnt, struct inode *dir, - struct dentry *new_dentry) + struct dentry *new_dentry, + struct vfsmount *new_mnt) { if (unlikely (IS_PRIVATE (old_dentry-d_inode))) return 0; - return security_ops-inode_link (old_dentry, dir, new_dentry); + return security_ops-inode_link (old_dentry, old_mnt, dir, +new_dentry, new_mnt); } static inline int security_inode_unlink (struct inode *dir, @@ -2359,8 +2365,10 @@ static inline int security_inode_create } static inline int security_inode_link (struct dentry *old_dentry, + struct vfsmount *old_mnt, struct inode *dir, - struct dentry *new_dentry) + struct dentry *new_dentry, + struct vfsmount *new_mnt) { return 0; } --- a/security/dummy.c +++ b/security/dummy.c @@ -270,8 +270,10 @@ static int dummy_inode_create (struct in return 0; } -static int dummy_inode_link (struct dentry *old_dentry, struct inode *inode, -struct dentry *new_dentry) +static int dummy_inode_link (struct dentry *old_dentry, +struct vfsmount *old_mnt, struct inode *inode, +struct dentry *new_dentry, +struct vfsmount *new_mnt) { return 0; } --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2182,11 +2182,16 @@ static int selinux_inode_create(struct i return may_create(dir, dentry, SECCLASS_FILE); } -static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) +static int selinux_inode_link(struct dentry *old_dentry, + struct vfsmount *old_mnt, + struct inode *dir, + struct dentry *new_dentry, + struct vfsmount *new_mnt) { int rc; - rc = secondary_ops-inode_link(old_dentry,dir,new_dentry); + rc = secondary_ops-inode_link(old_dentry, old_mnt, dir, new_dentry, + new_mnt); if (rc)
[AppArmor 14/44] Add a struct vfsmount parameter to vfs_rmdir()
The vfsmount will be passed down to the LSM hook so that LSMs can compute pathnames. Signed-off-by: Tony Jones [EMAIL PROTECTED] Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] --- fs/ecryptfs/inode.c |4 +++- fs/namei.c|4 ++-- fs/nfsd/nfs4recover.c |2 +- fs/nfsd/vfs.c |8 +--- fs/reiserfs/xattr.c |2 +- include/linux/fs.h|2 +- 6 files changed, 13 insertions(+), 9 deletions(-) --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -542,14 +542,16 @@ out: static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) { struct dentry *lower_dentry; + struct vfsmount *lower_mnt; struct dentry *lower_dir_dentry; int rc; lower_dentry = ecryptfs_dentry_to_lower(dentry); + lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); dget(dentry); lower_dir_dentry = lock_parent(lower_dentry); dget(lower_dentry); - rc = vfs_rmdir(lower_dir_dentry-d_inode, lower_dentry); + rc = vfs_rmdir(lower_dir_dentry-d_inode, lower_dentry, lower_mnt); dput(lower_dentry); if (!rc) d_delete(lower_dentry); --- a/fs/namei.c +++ b/fs/namei.c @@ -2024,7 +2024,7 @@ void dentry_unhash(struct dentry *dentry spin_unlock(dcache_lock); } -int vfs_rmdir(struct inode *dir, struct dentry *dentry) +int vfs_rmdir(struct inode *dir, struct dentry *dentry,struct vfsmount *mnt) { int error = may_delete(dir, dentry, 1); @@ -2088,7 +2088,7 @@ static long do_rmdir(int dfd, const char error = PTR_ERR(dentry); if (IS_ERR(dentry)) goto exit2; - error = vfs_rmdir(nd.dentry-d_inode, dentry); + error = vfs_rmdir(nd.dentry-d_inode, dentry, nd.mnt); dput(dentry); exit2: mutex_unlock(nd.dentry-d_inode-i_mutex); --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -276,7 +276,7 @@ nfsd4_clear_clid_dir(struct dentry *dir, * a kernel from the future */ nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file); mutex_lock_nested(dir-d_inode-i_mutex, I_MUTEX_PARENT); - status = vfs_rmdir(dir-d_inode, dentry); + status = vfs_rmdir(dir-d_inode, dentry, rec_dir.mnt); mutex_unlock(dir-d_inode-i_mutex); return status; } --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1666,6 +1666,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru char *fname, int flen) { struct dentry *dentry, *rdentry; + struct svc_export *exp; struct inode*dirp; __be32 err; int host_err; @@ -1680,6 +1681,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru fh_lock_nested(fhp, I_MUTEX_PARENT); dentry = fhp-fh_dentry; dirp = dentry-d_inode; + exp = fhp-fh_export; rdentry = lookup_one_len(fname, dentry, flen); host_err = PTR_ERR(rdentry); @@ -1697,21 +1699,21 @@ nfsd_unlink(struct svc_rqst *rqstp, stru if (type != S_IFDIR) { /* It's UNLINK */ #ifdef MSNFS - if ((fhp-fh_export-ex_flags NFSEXP_MSNFS) + if ((exp-ex_flags NFSEXP_MSNFS) (atomic_read(rdentry-d_count) 1)) { host_err = -EPERM; } else #endif host_err = vfs_unlink(dirp, rdentry); } else { /* It's RMDIR */ - host_err = vfs_rmdir(dirp, rdentry); + host_err = vfs_rmdir(dirp, rdentry, exp-ex_mnt); } dput(rdentry); if (host_err) goto out_nfserr; - if (EX_ISSYNC(fhp-fh_export)) + if (EX_ISSYNC(exp)) host_err = nfsd_sync_dir(dentry); out_nfserr: --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -775,7 +775,7 @@ int reiserfs_delete_xattrs(struct inode if (dir-d_inode-i_nlink = 2) { root = get_xa_root(inode-i_sb, XATTR_REPLACE); reiserfs_write_lock_xattrs(inode-i_sb); - err = vfs_rmdir(root-d_inode, dir); + err = vfs_rmdir(root-d_inode, dir, NULL); reiserfs_write_unlock_xattrs(inode-i_sb); dput(root); } else { --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -997,7 +997,7 @@ extern int vfs_mkdir(struct inode *, str extern int vfs_mknod(struct inode *, struct dentry *, struct vfsmount *, int, dev_t); extern int vfs_symlink(struct inode *, struct dentry *, struct vfsmount *, const char *, int); extern int vfs_link(struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *); -extern int vfs_rmdir(struct inode *, struct dentry *); +extern int vfs_rmdir(struct inode *, struct dentry *, struct vfsmount *); extern int vfs_unlink(struct inode *, struct dentry *); extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); -- - To unsubscribe from this list: send
[AppArmor 15/44] Pass struct vfsmount to the inode_rmdir LSM hook
This is needed for computing pathnames in the AppArmor LSM. Signed-off-by: Tony Jones [EMAIL PROTECTED] Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] --- fs/namei.c |2 +- include/linux/security.h | 12 security/dummy.c |3 ++- security/selinux/hooks.c |3 ++- 4 files changed, 13 insertions(+), 7 deletions(-) --- a/fs/namei.c +++ b/fs/namei.c @@ -2041,7 +2041,7 @@ int vfs_rmdir(struct inode *dir, struct if (d_mountpoint(dentry)) error = -EBUSY; else { - error = security_inode_rmdir(dir, dentry); + error = security_inode_rmdir(dir, dentry, mnt); if (!error) { error = dir-i_op-rmdir(dir, dentry); if (!error) --- a/include/linux/security.h +++ b/include/linux/security.h @@ -318,6 +318,7 @@ struct request_sock; * Check the permission to remove a directory. * @dir contains the inode structure of parent of the directory to be removed. * @dentry contains the dentry structure of directory to be removed. + * @mnt is the vfsmount corresponding to @dentry (may be NULL). * Return 0 if permission is granted. * @inode_mknod: * Check permissions when creating a special file (or a socket or a fifo @@ -1222,7 +1223,8 @@ struct security_operations { struct vfsmount *mnt, const char *old_name); int (*inode_mkdir) (struct inode *dir, struct dentry *dentry, struct vfsmount *mnt, int mode); - int (*inode_rmdir) (struct inode *dir, struct dentry *dentry); + int (*inode_rmdir) (struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt); int (*inode_mknod) (struct inode *dir, struct dentry *dentry, struct vfsmount *mnt, int mode, dev_t dev); int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry, @@ -1671,11 +1673,12 @@ static inline int security_inode_mkdir ( } static inline int security_inode_rmdir (struct inode *dir, - struct dentry *dentry) + struct dentry *dentry, + struct vfsmount *mnt) { if (unlikely (IS_PRIVATE (dentry-d_inode))) return 0; - return security_ops-inode_rmdir (dir, dentry); + return security_ops-inode_rmdir (dir, dentry, mnt); } static inline int security_inode_mknod (struct inode *dir, @@ -2396,7 +2399,8 @@ static inline int security_inode_mkdir ( } static inline int security_inode_rmdir (struct inode *dir, - struct dentry *dentry) + struct dentry *dentry, + struct vfsmount *mnt) { return 0; } --- a/security/dummy.c +++ b/security/dummy.c @@ -295,7 +295,8 @@ static int dummy_inode_mkdir (struct ino return 0; } -static int dummy_inode_rmdir (struct inode *inode, struct dentry *dentry) +static int dummy_inode_rmdir (struct inode *inode, struct dentry *dentry, + struct vfsmount *mnt) { return 0; } --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2219,7 +2219,8 @@ static int selinux_inode_mkdir(struct in return may_create(dir, dentry, SECCLASS_DIR); } -static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry) +static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt) { return may_link(dir, dentry, MAY_RMDIR); } -- - 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
[AppArmor 17/44] Add a struct vfsmount parameter to vfs_unlink()
The vfsmount will be passed down to the LSM hook so that LSMs can compute pathnames. Signed-off-by: Tony Jones [EMAIL PROTECTED] Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] --- fs/ecryptfs/inode.c |3 ++- fs/namei.c|4 ++-- fs/nfsd/nfs4recover.c |2 +- fs/nfsd/vfs.c |2 +- include/linux/fs.h|2 +- ipc/mqueue.c |2 +- 6 files changed, 8 insertions(+), 7 deletions(-) --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -453,10 +453,11 @@ static int ecryptfs_unlink(struct inode { int rc = 0; struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); + struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir); lock_parent(lower_dentry); - rc = vfs_unlink(lower_dir_inode, lower_dentry); + rc = vfs_unlink(lower_dir_inode, lower_dentry, lower_mnt); if (rc) { printk(KERN_ERR Error in vfs_unlink; rc = [%d]\n, rc); goto out_unlock; --- a/fs/namei.c +++ b/fs/namei.c @@ -2105,7 +2105,7 @@ asmlinkage long sys_rmdir(const char __u return do_rmdir(AT_FDCWD, pathname); } -int vfs_unlink(struct inode *dir, struct dentry *dentry) +int vfs_unlink(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt) { int error = may_delete(dir, dentry, 0); @@ -2169,7 +2169,7 @@ static long do_unlinkat(int dfd, const c inode = dentry-d_inode; if (inode) atomic_inc(inode-i_count); - error = vfs_unlink(nd.dentry-d_inode, dentry); + error = vfs_unlink(nd.dentry-d_inode, dentry, nd.mnt); exit2: dput(dentry); } --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -261,7 +261,7 @@ nfsd4_remove_clid_file(struct dentry *di return -EINVAL; } mutex_lock_nested(dir-d_inode-i_mutex, I_MUTEX_PARENT); - status = vfs_unlink(dir-d_inode, dentry); + status = vfs_unlink(dir-d_inode, dentry, rec_dir.mnt); mutex_unlock(dir-d_inode-i_mutex); return status; } --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1704,7 +1704,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru host_err = -EPERM; } else #endif - host_err = vfs_unlink(dirp, rdentry); + host_err = vfs_unlink(dirp, rdentry, exp-ex_mnt); } else { /* It's RMDIR */ host_err = vfs_rmdir(dirp, rdentry, exp-ex_mnt); } --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -998,7 +998,7 @@ extern int vfs_mknod(struct inode *, str extern int vfs_symlink(struct inode *, struct dentry *, struct vfsmount *, const char *, int); extern int vfs_link(struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *); extern int vfs_rmdir(struct inode *, struct dentry *, struct vfsmount *); -extern int vfs_unlink(struct inode *, struct dentry *); +extern int vfs_unlink(struct inode *, struct dentry *, struct vfsmount *); extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); /* --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -748,7 +748,7 @@ asmlinkage long sys_mq_unlink(const char if (inode) atomic_inc(inode-i_count); - err = vfs_unlink(dentry-d_parent-d_inode, dentry); + err = vfs_unlink(dentry-d_parent-d_inode, dentry, mqueue_mnt); out_err: dput(dentry); -- - 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
[AppArmor 18/44] Pass struct vfsmount to the inode_unlink LSM hook
This is needed for computing pathnames in the AppArmor LSM. Signed-off-by: Tony Jones [EMAIL PROTECTED] Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] --- fs/namei.c |2 +- include/linux/security.h | 12 security/dummy.c |3 ++- security/selinux/hooks.c |5 +++-- 4 files changed, 14 insertions(+), 8 deletions(-) --- a/fs/namei.c +++ b/fs/namei.c @@ -2121,7 +2121,7 @@ int vfs_unlink(struct inode *dir, struct if (d_mountpoint(dentry)) error = -EBUSY; else { - error = security_inode_unlink(dir, dentry); + error = security_inode_unlink(dir, dentry, mnt); if (!error) error = dir-i_op-unlink(dir, dentry); } --- a/include/linux/security.h +++ b/include/linux/security.h @@ -298,6 +298,7 @@ struct request_sock; * Check the permission to remove a hard link to a file. * @dir contains the inode structure of parent directory of the file. * @dentry contains the dentry structure for file to be unlinked. + * @mnt is the vfsmount corresponding to @dentry (may be NULL). * Return 0 if permission is granted. * @inode_symlink: * Check the permission to create a symbolic link to a file. @@ -1218,7 +1219,8 @@ struct security_operations { int (*inode_link) (struct dentry *old_dentry, struct vfsmount *old_mnt, struct inode *dir, struct dentry *new_dentry, struct vfsmount *new_mnt); - int (*inode_unlink) (struct inode *dir, struct dentry *dentry); + int (*inode_unlink) (struct inode *dir, struct dentry *dentry, +struct vfsmount *mnt); int (*inode_symlink) (struct inode *dir, struct dentry *dentry, struct vfsmount *mnt, const char *old_name); int (*inode_mkdir) (struct inode *dir, struct dentry *dentry, @@ -1645,11 +1647,12 @@ static inline int security_inode_link (s } static inline int security_inode_unlink (struct inode *dir, -struct dentry *dentry) +struct dentry *dentry, +struct vfsmount *mnt) { if (unlikely (IS_PRIVATE (dentry-d_inode))) return 0; - return security_ops-inode_unlink (dir, dentry); + return security_ops-inode_unlink (dir, dentry, mnt); } static inline int security_inode_symlink (struct inode *dir, @@ -2377,7 +2380,8 @@ static inline int security_inode_link (s } static inline int security_inode_unlink (struct inode *dir, -struct dentry *dentry) +struct dentry *dentry, +struct vfsmount *mnt) { return 0; } --- a/security/dummy.c +++ b/security/dummy.c @@ -278,7 +278,8 @@ static int dummy_inode_link (struct dent return 0; } -static int dummy_inode_unlink (struct inode *inode, struct dentry *dentry) +static int dummy_inode_unlink (struct inode *inode, struct dentry *dentry, + struct vfsmount *mnt) { return 0; } --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2197,11 +2197,12 @@ static int selinux_inode_link(struct den return may_link(dir, old_dentry, MAY_LINK); } -static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry) +static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry, + struct vfsmount *mnt) { int rc; - rc = secondary_ops-inode_unlink(dir, dentry); + rc = secondary_ops-inode_unlink(dir, dentry, mnt); if (rc) return rc; return may_link(dir, dentry, MAY_UNLINK); -- - 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
[AppArmor 16/44] Call lsm hook before unhashing dentry in vfs_rmdir()
If we unhash the dentry before calling the security_inode_rmdir hook, we cannot compute the file's pathname in the hook anymore. AppArmor needs to know the filename in order to decide whether a file may be deleted, though. Signed-off-by: John Johansen [EMAIL PROTECTED] Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] --- fs/namei.c | 13 +++-- 1 file changed, 7 insertions(+), 6 deletions(-) --- a/fs/namei.c +++ b/fs/namei.c @@ -2034,6 +2034,10 @@ int vfs_rmdir(struct inode *dir, struct if (!dir-i_op || !dir-i_op-rmdir) return -EPERM; + error = security_inode_rmdir(dir, dentry, mnt); + if (error) + return error; + DQUOT_INIT(dir); mutex_lock(dentry-d_inode-i_mutex); @@ -2041,12 +2045,9 @@ int vfs_rmdir(struct inode *dir, struct if (d_mountpoint(dentry)) error = -EBUSY; else { - error = security_inode_rmdir(dir, dentry, mnt); - if (!error) { - error = dir-i_op-rmdir(dir, dentry); - if (!error) - dentry-d_inode-i_flags |= S_DEAD; - } + error = dir-i_op-rmdir(dir, dentry); + if (!error) + dentry-d_inode-i_flags |= S_DEAD; } mutex_unlock(dentry-d_inode-i_mutex); if (!error) { -- - 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
[AppArmor 23/44] Add a struct vfsmount parameter to vfs_getxattr()
The vfsmount will be passed down to the LSM hook so that LSMs can compute pathnames. Signed-off-by: Tony Jones [EMAIL PROTECTED] Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] --- fs/nfsd/nfs4xdr.c |2 +- fs/nfsd/vfs.c | 21 - fs/xattr.c| 14 -- include/linux/nfsd/nfsd.h |3 ++- include/linux/xattr.h |3 ++- 5 files changed, 25 insertions(+), 18 deletions(-) --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1469,7 +1469,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, s } if (bmval0 (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT | FATTR4_WORD0_SUPPORTED_ATTRS)) { - err = nfsd4_get_nfs4_acl(rqstp, dentry, acl); + err = nfsd4_get_nfs4_acl(rqstp, dentry, exp-ex_mnt, acl); aclsupport = (err == 0); if (bmval0 FATTR4_WORD0_ACL) { if (err == -EOPNOTSUPP) --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -378,11 +378,12 @@ out_nfserr: #if defined(CONFIG_NFSD_V2_ACL) || \ defined(CONFIG_NFSD_V3_ACL) || \ defined(CONFIG_NFSD_V4) -static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf) +static ssize_t nfsd_getxattr(struct dentry *dentry, struct vfsmount *mnt, +char *key, void **buf) { ssize_t buflen; - buflen = vfs_getxattr(dentry, key, NULL, 0); + buflen = vfs_getxattr(dentry, mnt, key, NULL, 0); if (buflen = 0) return buflen; @@ -390,7 +391,7 @@ static ssize_t nfsd_getxattr(struct dent if (!*buf) return -ENOMEM; - return vfs_getxattr(dentry, key, *buf, buflen); + return vfs_getxattr(dentry, mnt, key, *buf, buflen); } #endif @@ -479,13 +480,13 @@ out_nfserr: } static struct posix_acl * -_get_posix_acl(struct dentry *dentry, char *key) +_get_posix_acl(struct dentry *dentry, struct vfsmount *mnt, char *key) { void *buf = NULL; struct posix_acl *pacl = NULL; int buflen; - buflen = nfsd_getxattr(dentry, key, buf); + buflen = nfsd_getxattr(dentry, mnt, key, buf); if (!buflen) buflen = -ENODATA; if (buflen = 0) @@ -497,14 +498,15 @@ _get_posix_acl(struct dentry *dentry, ch } int -nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_acl **acl) +nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, + struct vfsmount *mnt, struct nfs4_acl **acl) { struct inode *inode = dentry-d_inode; int error = 0; struct posix_acl *pacl = NULL, *dpacl = NULL; unsigned int flags = 0; - pacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_ACCESS); + pacl = _get_posix_acl(dentry, mnt, POSIX_ACL_XATTR_ACCESS); if (IS_ERR(pacl) PTR_ERR(pacl) == -ENODATA) pacl = posix_acl_from_mode(inode-i_mode, GFP_KERNEL); if (IS_ERR(pacl)) { @@ -514,7 +516,7 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqst } if (S_ISDIR(inode-i_mode)) { - dpacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_DEFAULT); + dpacl = _get_posix_acl(dentry, mnt, POSIX_ACL_XATTR_DEFAULT); if (IS_ERR(dpacl) PTR_ERR(dpacl) == -ENODATA) dpacl = NULL; else if (IS_ERR(dpacl)) { @@ -1942,7 +1944,8 @@ nfsd_get_posix_acl(struct svc_fh *fhp, i return ERR_PTR(-EOPNOTSUPP); } - size = nfsd_getxattr(fhp-fh_dentry, name, value); + size = nfsd_getxattr(fhp-fh_dentry, fhp-fh_export-ex_mnt, name, +value); if (size 0) return ERR_PTR(size); --- a/fs/xattr.c +++ b/fs/xattr.c @@ -106,7 +106,8 @@ out: EXPORT_SYMBOL_GPL(vfs_setxattr); ssize_t -vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size) +vfs_getxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, +void *value, size_t size) { struct inode *inode = dentry-d_inode; int error; @@ -278,7 +279,8 @@ sys_fsetxattr(int fd, char __user *name, * Extended attribute GET operations */ static ssize_t -getxattr(struct dentry *d, char __user *name, void __user *value, size_t size) +getxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name, +void __user *value, size_t size) { ssize_t error; void *kvalue = NULL; @@ -298,7 +300,7 @@ getxattr(struct dentry *d, char __user * return -ENOMEM; } - error = vfs_getxattr(d, kname, kvalue, size); + error = vfs_getxattr(dentry, mnt, kname, kvalue, size); if (error 0) { if (size copy_to_user(value, kvalue, error)) error = -EFAULT; @@ -321,7 +323,7 @@ sys_getxattr(char __user *path, char __u error = user_path_walk(path, nd); if
[AppArmor 21/44] Add a struct vfsmount parameter to vfs_setxattr()
The vfsmount will be passed down to the LSM hook so that LSMs can compute pathnames. Signed-off-by: Tony Jones [EMAIL PROTECTED] Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] --- fs/nfsd/vfs.c | 16 +++- fs/xattr.c| 16 include/linux/xattr.h |3 ++- 3 files changed, 21 insertions(+), 14 deletions(-) --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -396,7 +396,8 @@ static ssize_t nfsd_getxattr(struct dent #if defined(CONFIG_NFSD_V4) static int -set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key) +set_nfsv4_acl_one(struct dentry *dentry, struct vfsmount *mnt, + struct posix_acl *pacl, char *key) { int len; size_t buflen; @@ -415,7 +416,7 @@ set_nfsv4_acl_one(struct dentry *dentry, goto out; } - error = vfs_setxattr(dentry, key, buf, len, 0); + error = vfs_setxattr(dentry, mnt, key, buf, len, 0); out: kfree(buf); return error; @@ -428,6 +429,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst __be32 error; int host_error; struct dentry *dentry; + struct vfsmount *mnt; struct inode *inode; struct posix_acl *pacl = NULL, *dpacl = NULL; unsigned int flags = 0; @@ -438,6 +440,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst goto out; dentry = fhp-fh_dentry; + mnt = fhp-fh_export-ex_mnt; inode = dentry-d_inode; if (S_ISDIR(inode-i_mode)) flags = NFS4_ACL_DIR; @@ -449,12 +452,14 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst } else if (host_error 0) goto out_nfserr; - host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS); + host_error = set_nfsv4_acl_one(dentry, mnt, pacl, + POSIX_ACL_XATTR_ACCESS); if (host_error 0) goto out_nfserr; if (S_ISDIR(inode-i_mode)) { - host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT); + host_error = set_nfsv4_acl_one(dentry, mnt, dpacl, + POSIX_ACL_XATTR_DEFAULT); if (host_error 0) goto out_nfserr; } @@ -1982,7 +1987,8 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i size = 0; if (size) - error = vfs_setxattr(fhp-fh_dentry, name, value, size, 0); + error = vfs_setxattr(fhp-fh_dentry, fhp-fh_export-ex_mnt, +name, value, size,0); else { if (!S_ISDIR(inode-i_mode) type == ACL_TYPE_DEFAULT) error = 0; --- a/fs/xattr.c +++ b/fs/xattr.c @@ -69,8 +69,8 @@ xattr_permission(struct inode *inode, co } int -vfs_setxattr(struct dentry *dentry, char *name, void *value, - size_t size, int flags) +vfs_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, +void *value, size_t size, int flags) { struct inode *inode = dentry-d_inode; int error; @@ -193,8 +193,8 @@ EXPORT_SYMBOL_GPL(vfs_removexattr); * Extended attribute SET operations */ static long -setxattr(struct dentry *d, char __user *name, void __user *value, -size_t size, int flags) +setxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name, +void __user *value, size_t size, int flags) { int error; void *kvalue = NULL; @@ -221,7 +221,7 @@ setxattr(struct dentry *d, char __user * } } - error = vfs_setxattr(d, kname, kvalue, size, flags); + error = vfs_setxattr(dentry, mnt, kname, kvalue, size, flags); kfree(kvalue); return error; } @@ -236,7 +236,7 @@ sys_setxattr(char __user *path, char __u error = user_path_walk(path, nd); if (error) return error; - error = setxattr(nd.dentry, name, value, size, flags); + error = setxattr(nd.dentry, nd.mnt, name, value, size, flags); path_release(nd); return error; } @@ -251,7 +251,7 @@ sys_lsetxattr(char __user *path, char __ error = user_path_walk_link(path, nd); if (error) return error; - error = setxattr(nd.dentry, name, value, size, flags); + error = setxattr(nd.dentry, nd.mnt, name, value, size, flags); path_release(nd); return error; } @@ -269,7 +269,7 @@ sys_fsetxattr(int fd, char __user *name, return error; dentry = f-f_path.dentry; audit_inode(NULL, dentry-d_inode); - error = setxattr(dentry, name, value, size, flags); + error = setxattr(dentry, f-f_vfsmnt, name, value, size, flags); fput(f); return error; } --- a/include/linux/xattr.h +++ b/include/linux/xattr.h @@ -48,7 +48,8 @@ struct xattr_handler { ssize_t vfs_getxattr(struct
[AppArmor 26/44] Pass struct vfsmount to the inode_listxattr LSM hook
This is needed for computing pathnames in the AppArmor LSM. Signed-off-by: Tony Jones [EMAIL PROTECTED] Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] --- fs/xattr.c |2 +- include/linux/security.h | 12 +++- security/dummy.c |2 +- security/selinux/hooks.c |2 +- 4 files changed, 10 insertions(+), 8 deletions(-) --- a/fs/xattr.c +++ b/fs/xattr.c @@ -149,7 +149,7 @@ vfs_listxattr(struct dentry *dentry, str struct inode *inode = dentry-d_inode; ssize_t error; - error = security_inode_listxattr(dentry); + error = security_inode_listxattr(dentry, mnt); if (error) return error; error = -EOPNOTSUPP; --- a/include/linux/security.h +++ b/include/linux/security.h @@ -395,7 +395,7 @@ struct request_sock; * Return 0 if permission is granted. * @inode_listxattr: * Check permission before obtaining the list of extended attribute - * names for @dentry. + * names for @dentry and @mnt. * Return 0 if permission is granted. * @inode_removexattr: * Check permission before removing the extended attribute @@ -1250,7 +1250,7 @@ struct security_operations { size_t size, int flags); int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt, char *name); - int (*inode_listxattr) (struct dentry *dentry); + int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt); int (*inode_removexattr) (struct dentry *dentry, char *name); const char *(*inode_xattr_getsuffix) (void); int (*inode_getsecurity)(const struct inode *inode, const char *name, void *buffer, size_t size, int err); @@ -1791,11 +1791,12 @@ static inline int security_inode_getxatt return security_ops-inode_getxattr (dentry, mnt, name); } -static inline int security_inode_listxattr (struct dentry *dentry) +static inline int security_inode_listxattr (struct dentry *dentry, + struct vfsmount *mnt) { if (unlikely (IS_PRIVATE (dentry-d_inode))) return 0; - return security_ops-inode_listxattr (dentry); + return security_ops-inode_listxattr (dentry, mnt); } static inline int security_inode_removexattr (struct dentry *dentry, char *name) @@ -2495,7 +2496,8 @@ static inline int security_inode_getxatt return 0; } -static inline int security_inode_listxattr (struct dentry *dentry) +static inline int security_inode_listxattr (struct dentry *dentry, + struct vfsmount *mnt) { return 0; } --- a/security/dummy.c +++ b/security/dummy.c @@ -374,7 +374,7 @@ static int dummy_inode_getxattr (struct return 0; } -static int dummy_inode_listxattr (struct dentry *dentry) +static int dummy_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt) { return 0; } --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2399,7 +2399,7 @@ static int selinux_inode_getxattr (struc return dentry_has_perm(current, NULL, dentry, FILE__GETATTR); } -static int selinux_inode_listxattr (struct dentry *dentry) +static int selinux_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt) { return dentry_has_perm(current, NULL, dentry, FILE__GETATTR); } -- - 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
[AppArmor 12/44] Add struct vfsmount parameters to vfs_link()
The vfsmount will be passed down to the LSM hook so that LSMs can compute pathnames. Signed-off-by: Tony Jones [EMAIL PROTECTED] Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] --- fs/ecryptfs/inode.c |9 +++-- fs/namei.c |5 +++-- fs/nfsd/vfs.c |3 ++- include/linux/fs.h |2 +- 4 files changed, 13 insertions(+), 6 deletions(-) --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -411,19 +411,24 @@ static int ecryptfs_link(struct dentry * struct dentry *new_dentry) { struct dentry *lower_old_dentry; + struct vfsmount *lower_old_mnt; struct dentry *lower_new_dentry; + struct vfsmount *lower_new_mnt; struct dentry *lower_dir_dentry; u64 file_size_save; int rc; file_size_save = i_size_read(old_dentry-d_inode); lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry); + lower_old_mnt = ecryptfs_dentry_to_lower_mnt(old_dentry); lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry); + lower_new_mnt = ecryptfs_dentry_to_lower_mnt(new_dentry); dget(lower_old_dentry); dget(lower_new_dentry); lower_dir_dentry = lock_parent(lower_new_dentry); - rc = vfs_link(lower_old_dentry, lower_dir_dentry-d_inode, - lower_new_dentry); + rc = vfs_link(lower_old_dentry, lower_old_mnt, + lower_dir_dentry-d_inode, lower_new_dentry, + lower_new_mnt); if (rc || !lower_new_dentry-d_inode) goto out_lock; rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir-i_sb, 0); --- a/fs/namei.c +++ b/fs/namei.c @@ -2268,7 +2268,7 @@ asmlinkage long sys_symlink(const char _ return sys_symlinkat(oldname, AT_FDCWD, newname); } -int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) +int vfs_link(struct dentry *old_dentry, struct vfsmount *old_mnt, struct inode *dir, struct dentry *new_dentry, struct vfsmount *new_mnt) { struct inode *inode = old_dentry-d_inode; int error; @@ -2346,7 +2346,8 @@ asmlinkage long sys_linkat(int olddfd, c error = PTR_ERR(new_dentry); if (IS_ERR(new_dentry)) goto out_unlock; - error = vfs_link(old_nd.dentry, nd.dentry-d_inode, new_dentry); + error = vfs_link(old_nd.dentry, old_nd.mnt, nd.dentry-d_inode, +new_dentry, nd.mnt); dput(new_dentry); out_unlock: mutex_unlock(nd.dentry-d_inode-i_mutex); --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1536,7 +1536,8 @@ nfsd_link(struct svc_rqst *rqstp, struct dold = tfhp-fh_dentry; dest = dold-d_inode; - host_err = vfs_link(dold, dirp, dnew); + host_err = vfs_link(dold, tfhp-fh_export-ex_mnt, dirp, + dnew, ffhp-fh_export-ex_mnt); if (!host_err) { if (EX_ISSYNC(ffhp-fh_export)) { err = nfserrno(nfsd_sync_dir(ddir)); --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -996,7 +996,7 @@ extern int vfs_create(struct inode *, st extern int vfs_mkdir(struct inode *, struct dentry *, struct vfsmount *, int); extern int vfs_mknod(struct inode *, struct dentry *, struct vfsmount *, int, dev_t); extern int vfs_symlink(struct inode *, struct dentry *, struct vfsmount *, const char *, int); -extern int vfs_link(struct dentry *, struct inode *, struct dentry *); +extern int vfs_link(struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *); extern int vfs_rmdir(struct inode *, struct dentry *); extern int vfs_unlink(struct inode *, struct dentry *); extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); -- - 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
[AppArmor 29/44] Fix __d_path() for lazy unmounts and make it unambiguous
First, when __d_path() hits a lazily unmounted mount point, it tries to prepend the name of the lazily unmounted dentry to the path name. It gets this wrong, and also overwrites the slash that separates the name from the following pathname component. This patch fixes that; if a process was in directory /foo/bar and /foo got lazily unmounted, the old result was ``foobar'' (note the missing slash), while the new result with this patch is ``foo/bar''. Second, it isn't always possible to tell from the __d_path() result whether the specified root and rootmnt (i.e., the chroot) was reached. We need an unambiguous result for AppArmor at least though, so we make sure that paths will only start with a slash if the path leads all the way up to the root. We also add a @fail_deleted argument, which allows to get rid of some of the mess in sys_getcwd(). This patch leaves getcwd() and d_path() as they were before for everything except for bind-mounted directories; for them, it reports ``/foo/bar'' instead of ``foobar'' in the example described above. Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] Acked-by: Alan Cox [EMAIL PROTECTED] --- fs/dcache.c | 169 ++-- 1 file changed, 98 insertions(+), 71 deletions(-) --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1761,52 +1761,51 @@ shouldnt_be_hashed: } /** - * d_path - return the path of a dentry + * __d_path - return the path of a dentry * @dentry: dentry to report * @vfsmnt: vfsmnt to which the dentry belongs * @root: root dentry * @rootmnt: vfsmnt to which the root dentry belongs * @buffer: buffer to return value in * @buflen: buffer length + * @fail_deleted: what to return for deleted files * - * Convert a dentry into an ASCII path name. If the entry has been deleted + * Convert a dentry into an ASCII path name. If the entry has been deleted, + * then if @fail_deleted is true, ERR_PTR(-ENOENT) is returned. Otherwise, * the string (deleted) is appended. Note that this is ambiguous. * - * Returns the buffer or an error code if the path was too long. + * If @dentry is not connected to @root, the path returned will be relative + * (i.e., it will not start with a slash). * - * buflen should be positive. Caller holds the dcache_lock. + * Returns the buffer or an error code. */ -static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt, - struct dentry *root, struct vfsmount *rootmnt, - char *buffer, int buflen) -{ - char * end = buffer+buflen; - char * retval; - int namelen; +static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt, + struct dentry *root, struct vfsmount *rootmnt, + char *buffer, int buflen, int fail_deleted) +{ + int namelen, is_slash; + + if (buflen 2) + return ERR_PTR(-ENAMETOOLONG); + buffer += --buflen; + *buffer = '\0'; - *--end = '\0'; - buflen--; + spin_lock(dcache_lock); if (!IS_ROOT(dentry) d_unhashed(dentry)) { - buflen -= 10; - end -= 10; - if (buflen 0) + if (fail_deleted) { + buffer = ERR_PTR(-ENOENT); + goto out; + } + if (buflen 10) goto Elong; - memcpy(end, (deleted), 10); + buflen -= 10; + buffer -= 10; + memcpy(buffer, (deleted), 10); } - - if (buflen 1) - goto Elong; - /* Get '/' right */ - retval = end-1; - *retval = '/'; - - for (;;) { + while (dentry != root || vfsmnt != rootmnt) { struct dentry * parent; - if (dentry == root vfsmnt == rootmnt) - break; if (dentry == vfsmnt-mnt_root || IS_ROOT(dentry)) { - /* Global root? */ spin_lock(vfsmount_lock); if (vfsmnt-mnt_parent == vfsmnt) { spin_unlock(vfsmount_lock); @@ -1820,33 +1819,72 @@ static char * __d_path( struct dentry *d parent = dentry-d_parent; prefetch(parent); namelen = dentry-d_name.len; - buflen -= namelen + 1; - if (buflen 0) + if (buflen namelen + 1) goto Elong; - end -= namelen; - memcpy(end, dentry-d_name.name, namelen); - *--end = '/'; - retval = end; + buflen -= namelen + 1; + buffer -= namelen; + memcpy(buffer, dentry-d_name.name, namelen); + *--buffer = '/'; dentry = parent; } + /* Get '/' right. */ + if (*buffer != '/') + *--buffer
[AppArmor 33/44] Pass struct file down the inode_*xattr security LSM hooks
This allows LSMs to also distinguish between file descriptor and path access for the xattr operations. (The other relevant operations are covered by the setattr hook.) Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] --- fs/xattr.c | 58 --- include/linux/security.h | 53 +- include/linux/xattr.h|8 +++--- security/commoncap.c |4 +-- security/dummy.c | 10 security/selinux/hooks.c | 10 6 files changed, 80 insertions(+), 63 deletions(-) --- a/fs/xattr.c +++ b/fs/xattr.c @@ -70,7 +70,7 @@ xattr_permission(struct inode *inode, co int vfs_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, -void *value, size_t size, int flags) +void *value, size_t size, int flags, struct file *file) { struct inode *inode = dentry-d_inode; int error; @@ -80,7 +80,7 @@ vfs_setxattr(struct dentry *dentry, stru return error; mutex_lock(inode-i_mutex); - error = security_inode_setxattr(dentry, mnt, name, value, size, flags); + error = security_inode_setxattr(dentry, mnt, name, value, size, flags, file); if (error) goto out; error = -EOPNOTSUPP; @@ -107,7 +107,7 @@ EXPORT_SYMBOL_GPL(vfs_setxattr); ssize_t vfs_getxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, -void *value, size_t size) +void *value, size_t size, struct file *file) { struct inode *inode = dentry-d_inode; int error; @@ -116,7 +116,7 @@ vfs_getxattr(struct dentry *dentry, stru if (error) return error; - error = security_inode_getxattr(dentry, mnt, name); + error = security_inode_getxattr(dentry, mnt, name, file); if (error) return error; @@ -144,12 +144,12 @@ EXPORT_SYMBOL_GPL(vfs_getxattr); ssize_t vfs_listxattr(struct dentry *dentry, struct vfsmount *mnt, char *list, - size_t size) + size_t size, struct file *file) { struct inode *inode = dentry-d_inode; ssize_t error; - error = security_inode_listxattr(dentry, mnt); + error = security_inode_listxattr(dentry, mnt, file); if (error) return error; error = -EOPNOTSUPP; @@ -165,7 +165,8 @@ vfs_listxattr(struct dentry *dentry, str EXPORT_SYMBOL_GPL(vfs_listxattr); int -vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name) +vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name, + struct file *file) { struct inode *inode = dentry-d_inode; int error; @@ -177,7 +178,7 @@ vfs_removexattr(struct dentry *dentry, s if (error) return error; - error = security_inode_removexattr(dentry, mnt, name); + error = security_inode_removexattr(dentry, mnt, name, file); if (error) return error; @@ -197,7 +198,7 @@ EXPORT_SYMBOL_GPL(vfs_removexattr); */ static long setxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name, -void __user *value, size_t size, int flags) +void __user *value, size_t size, int flags, struct file *file) { int error; void *kvalue = NULL; @@ -224,7 +225,7 @@ setxattr(struct dentry *dentry, struct v } } - error = vfs_setxattr(dentry, mnt, kname, kvalue, size, flags); + error = vfs_setxattr(dentry, mnt, kname, kvalue, size, flags, file); kfree(kvalue); return error; } @@ -239,7 +240,7 @@ sys_setxattr(char __user *path, char __u error = user_path_walk(path, nd); if (error) return error; - error = setxattr(nd.dentry, nd.mnt, name, value, size, flags); + error = setxattr(nd.dentry, nd.mnt, name, value, size, flags, NULL); path_release(nd); return error; } @@ -254,7 +255,7 @@ sys_lsetxattr(char __user *path, char __ error = user_path_walk_link(path, nd); if (error) return error; - error = setxattr(nd.dentry, nd.mnt, name, value, size, flags); + error = setxattr(nd.dentry, nd.mnt, name, value, size, flags, NULL); path_release(nd); return error; } @@ -272,7 +273,7 @@ sys_fsetxattr(int fd, char __user *name, return error; dentry = f-f_path.dentry; audit_inode(NULL, dentry-d_inode); - error = setxattr(dentry, f-f_vfsmnt, name, value, size, flags); + error = setxattr(dentry, f-f_vfsmnt, name, value, size, flags, f); fput(f); return error; } @@ -282,7 +283,7 @@ sys_fsetxattr(int fd, char __user *name, */ static ssize_t getxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name, -void __user *value, size_t
[AppArmor 36/44] Export audit subsystem for use by modules
Update kenel audit range comments to show AppArmor's registered range of 1500-1599. This range used to be reserved for LSPP but LSPP uses the SE Linux range and the range was given to AppArmor. Adds necessary export symbols for audit subsystem routines. Changes audit_log_vformat to be externally visible (analagous to vprintf) Patch is not in mainline -- pending AppArmor code submission to lkml Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] --- include/linux/audit.h | 12 +++- kernel/audit.c|6 -- 2 files changed, 15 insertions(+), 3 deletions(-) --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -33,7 +33,7 @@ * 1200 - 1299 messages internal to the audit daemon * 1300 - 1399 audit event messages * 1400 - 1499 SE Linux use - * 1500 - 1599 kernel LSPP events + * 1500 - 1599 AppArmor use * 1600 - 1699 kernel crypto events * 1700 - 1799 kernel anomaly records * 1800 - 1999 future kernel use (maybe integrity labels and related events) @@ -109,6 +109,13 @@ #define AUDIT_MAC_IPSEC_ADDSPD 1413/* Add a XFRM policy */ #define AUDIT_MAC_IPSEC_DELSPD 1414/* Delete a XFRM policy */ +#define AUDIT_APPARMOR_AUDIT 1501/* AppArmor audited grants */ +#define AUDIT_APPARMOR_ALLOWED 1502/* Allowed Access for learning */ +#define AUDIT_APPARMOR_DENIED 1503 +#define AUDIT_APPARMOR_HINT1504/* Process Tracking information */ +#define AUDIT_APPARMOR_STATUS 1505/* Changes in config */ +#define AUDIT_APPARMOR_ERROR 1506/* Internal AppArmor Errors */ + #define AUDIT_FIRST_KERN_ANOM_MSG 1700 #define AUDIT_LAST_KERN_ANOM_MSG1799 #define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */ @@ -499,6 +506,9 @@ extern void audit_log(struct audit_ __attribute__((format(printf,4,5))); extern struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type); +extern voidaudit_log_vformat(struct audit_buffer *ab, + const char *fmt, va_list args) + __attribute__((format(printf,2,0))); extern voidaudit_log_format(struct audit_buffer *ab, const char *fmt, ...) __attribute__((format(printf,2,3))); --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1054,8 +1054,7 @@ static inline int audit_expand(struct au * will be called a second time. Currently, we assume that a printk * can't format message larger than 1024 bytes, so we don't either. */ -static void audit_log_vformat(struct audit_buffer *ab, const char *fmt, - va_list args) +void audit_log_vformat(struct audit_buffer *ab, const char *fmt, va_list args) { int len, avail; struct sk_buff *skb; @@ -1311,3 +1310,6 @@ EXPORT_SYMBOL(audit_log_start); EXPORT_SYMBOL(audit_log_end); EXPORT_SYMBOL(audit_log_format); EXPORT_SYMBOL(audit_log); +EXPORT_SYMBOL_GPL(audit_log_vformat); +EXPORT_SYMBOL_GPL(audit_log_untrustedstring); +EXPORT_SYMBOL_GPL(audit_log_d_path); -- - 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
[AppArmor 37/44] AppArmor: Main Part
The underlying functions by which the AppArmor LSM hooks are implemented. Signed-off-by: John Johansen [EMAIL PROTECTED] Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] --- security/apparmor/main.c | 1255 +++ 1 file changed, 1255 insertions(+) --- /dev/null +++ b/security/apparmor/main.c @@ -0,0 +1,1255 @@ +/* + * Copyright (C) 2002-2007 Novell/SUSE + * + * 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 the Free Software Foundation, version 2 of the + * License. + * + * AppArmor Core + */ + +#include linux/security.h +#include linux/namei.h +#include linux/audit.h +#include linux/mount.h +#include linux/ptrace.h + +#include apparmor.h + +#include inline.h + +/* + * Table of capability names: we generate it from capabilities.h. + */ +static const char *capability_names[] = { +#include capability_names.h +}; + +/* NULL complain profile + * + * Used when in complain mode, to emit Permitting messages for non-existant + * profiles and hats. This is necessary because of selective mode, in which + * case we need a complain null_profile and enforce null_profile + * + * The null_complain_profile cannot be statically allocated, because it + * can be associated to files which keep their reference even if apparmor is + * unloaded + */ +struct aa_profile *null_complain_profile; + +/** + * aa_file_denied - check for @mask access on a file + * @profile: profile to check against + * @name: pathname of file + * @mask: permission mask requested for file + * + * Return %0 on success, or else the permissions in @mask that the + * profile denies. + */ +static int aa_file_denied(struct aa_profile *profile, const char *name, + int mask) +{ + return (mask ~aa_match(profile-file_rules, name)); +} + +/** + * aa_link_denied - check for permission to link a file + * @profile: profile to check against + * @link: pathname of link being created + * @target: pathname of target to be linked to + * @request_mask: the permissions subset valid only if link succeeds + * Return %0 on success, or else the permissions that the profile denies. + */ +static int aa_link_denied(struct aa_profile *profile, const char *link, + const char *target, int *request_mask) +{ + int l_mode, t_mode, denied_mask; + + l_mode = aa_match(profile-file_rules, link); + t_mode = aa_match(profile-file_rules, target); + + /* Ignore valid-profile-transition flags. */ + l_mode = ~AA_CHANGE_PROFILE; + t_mode = ~AA_CHANGE_PROFILE; + + *request_mask = l_mode | AA_MAY_LINK; + + /* Link always requires 'l' on the link, a subset of the +* target's 'r', 'w', 'x', and 'm' permissions on the link, and +* if the link has 'x', an exact match of all the execute flags +* ('i', 'u', 'U', 'p', 'P'). +*/ +#define RWXM (MAY_READ | MAY_WRITE | MAY_EXEC | AA_EXEC_MMAP) + denied_mask = ~l_mode AA_MAY_LINK; + if (l_mode RWXM) + denied_mask |= (l_mode ~ AA_MAY_LINK) ~t_mode; + else + denied_mask |= t_mode | AA_MAY_LINK; + if (denied_mask AA_EXEC_MODIFIERS) + denied_mask |= MAY_EXEC; + +#undef RWXM + + return denied_mask; +} + +/** + * aa_get_name - compute the pathname of a file + * @dentry: dentry of the file + * @mnt: vfsmount of the file + * @buffer: buffer that aa_get_name() allocated + * @check: AA_CHECK_DIR is set if the file is a directory + * + * Returns a pointer to the beginning of the pathname (which usually differs + * from the beginning of the buffer), or an error code. + * + * We need @check to indicate whether the file is a directory or not because + * the file may not yet exist, and so we cannot check the inode's file type. + */ +static char *aa_get_name(struct dentry *dentry, struct vfsmount *mnt, +char **buffer, int check) +{ + char *name; + int is_dir, size = 256; + + is_dir = (check AA_CHECK_DIR) ? 1 : 0; + + for (;;) { + char *buf = kmalloc(size, GFP_KERNEL); + if (!buf) + return ERR_PTR(-ENOMEM); + + name = d_namespace_path(dentry, mnt, buf, size - is_dir); + if (!IS_ERR(name)) { + if (name[0] != '/') { + /* +* This dentry is not connected to the +* namespace root -- reject access. +*/ + kfree(buf); + return ERR_PTR(-ENOENT); + } + if (is_dir name[1] != '\0') { + /* +* Append / to the pathname. The root +* directory is a
[AppArmor 38/44] AppArmor: Module and LSM hooks
Module parameters, LSM hooks, initialization and teardown. Signed-off-by: John Johansen [EMAIL PROTECTED] Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] --- security/apparmor/lsm.c | 817 1 file changed, 817 insertions(+) --- /dev/null +++ b/security/apparmor/lsm.c @@ -0,0 +1,817 @@ +/* + * Copyright (C) 1998-2007 Novell/SUSE + * + * 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 the Free Software Foundation, version 2 of the + * License. + * + * AppArmor LSM interface + */ + +#include linux/security.h +#include linux/module.h +#include linux/mm.h +#include linux/mman.h +#include linux/mount.h +#include linux/namei.h +#include linux/ctype.h +#include linux/sysctl.h +#include linux/audit.h + +#include apparmor.h +#include inline.h + +static int param_set_aabool(const char *val, struct kernel_param *kp); +static int param_get_aabool(char *buffer, struct kernel_param *kp); +#define param_check_aabool(name, p) __param_check(name, p, int) + +static int param_set_aauint(const char *val, struct kernel_param *kp); +static int param_get_aauint(char *buffer, struct kernel_param *kp); +#define param_check_aauint(name, p) __param_check(name, p, int) + +/* Flag values, also controllable via /sys/module/apparmor/parameters + * We define special types as we want to do additional mediation. + * + * Complain mode -- in complain mode access failures result in auditing only + * and task is allowed access. audit events are processed by userspace to + * generate policy. Default is 'enforce' (0). + * Value is also togglable per profile and referenced when global value is + * enforce. + */ +int apparmor_complain = 0; +module_param_named(complain, apparmor_complain, aabool, S_IRUSR | S_IWUSR); +MODULE_PARM_DESC(apparmor_complain, Toggle AppArmor complain mode); + +/* Debug mode */ +int apparmor_debug = 0; +module_param_named(debug, apparmor_debug, aabool, S_IRUSR | S_IWUSR); +MODULE_PARM_DESC(apparmor_debug, Toggle AppArmor debug mode); + +/* Audit mode */ +int apparmor_audit = 0; +module_param_named(audit, apparmor_audit, aabool, S_IRUSR | S_IWUSR); +MODULE_PARM_DESC(apparmor_audit, Toggle AppArmor audit mode); + +/* Syscall logging mode */ +int apparmor_logsyscall = 0; +module_param_named(logsyscall, apparmor_logsyscall, aabool, S_IRUSR | S_IWUSR); +MODULE_PARM_DESC(apparmor_logsyscall, Toggle AppArmor logsyscall mode); + +/* Maximum pathname length before accesses will start getting rejected */ +unsigned int apparmor_path_max = 2 * PATH_MAX; +module_param_named(path_max, apparmor_path_max, aauint, S_IRUSR | S_IWUSR); +MODULE_PARM_DESC(apparmor_path_max, Maximum pathname length allowed); + +static int param_set_aabool(const char *val, struct kernel_param *kp) +{ + if (aa_task_context(current)) + return -EPERM; + return param_set_bool(val, kp); +} + +static int param_get_aabool(char *buffer, struct kernel_param *kp) +{ + if (aa_task_context(current)) + return -EPERM; + return param_get_bool(buffer, kp); +} + +static int param_set_aauint(const char *val, struct kernel_param *kp) +{ + if (aa_task_context(current)) + return -EPERM; + return param_set_uint(val, kp); +} + +static int param_get_aauint(char *buffer, struct kernel_param *kp) +{ + if (aa_task_context(current)) + return -EPERM; + return param_get_uint(buffer, kp); +} + +static int aa_reject_syscall(struct task_struct *task, gfp_t flags, +const char *name) +{ + struct aa_profile *profile = aa_get_profile(task); + int error = 0; + + if (profile) { + error = aa_audit_syscallreject(profile, flags, name); + aa_put_profile(profile); + } + + return error; +} + +static int apparmor_ptrace(struct task_struct *parent, + struct task_struct *child) +{ + struct aa_task_context *cxt; + int error = 0; + + /* +* parent can ptrace child when +* - parent is unconfined +* - parent child are in the same namespace +* - parent is in complain mode +* - parent and child are confined by the same profile +* - parent profile has CAP_SYS_PTRACE +*/ + + rcu_read_lock(); + cxt = aa_task_context(parent); + if (cxt) { + if (parent-nsproxy != child-nsproxy) { + struct aa_audit sa; + memset(sa, 0, sizeof(sa)); + sa.operation = ptrace; + sa.gfp_mask = GFP_ATOMIC; + sa.parent = parent-pid; + sa.task = child-pid; + sa.info = different namespaces; + aa_audit_reject(cxt-profile, sa); + error = -EPERM; +
[AppArmor 04/44] Pass struct vfsmount to the inode_setattr LSM hook
This is needed for computing pathnames in the AppArmor LSM. Signed-off-by: Tony Jones [EMAIL PROTECTED] Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] --- fs/attr.c|4 ++-- include/linux/security.h |8 ++-- security/dummy.c |3 ++- security/selinux/hooks.c |5 +++-- 4 files changed, 13 insertions(+), 7 deletions(-) --- a/fs/attr.c +++ b/fs/attr.c @@ -144,13 +144,13 @@ int notify_change(struct dentry *dentry, down_write(dentry-d_inode-i_alloc_sem); if (inode-i_op inode-i_op-setattr) { - error = security_inode_setattr(dentry, attr); + error = security_inode_setattr(dentry, mnt, attr); if (!error) error = inode-i_op-setattr(dentry, attr); } else { error = inode_change_ok(inode, attr); if (!error) - error = security_inode_setattr(dentry, attr); + error = security_inode_setattr(dentry, mnt, attr); if (!error) { if ((ia_valid ATTR_UID attr-ia_uid != inode-i_uid) || (ia_valid ATTR_GID attr-ia_gid != inode-i_gid)) --- a/include/linux/security.h +++ b/include/linux/security.h @@ -358,6 +358,7 @@ struct request_sock; * file attributes change (such as when a file is truncated, chown/chmod * operations, transferring disk quotas, etc). * @dentry contains the dentry structure for the file. + * @mnt is the vfsmount corresponding to @dentry (may be NULL). * @attr is the iattr structure containing the new file attributes. * Return 0 if permission is granted. * @inode_getattr: @@ -1221,7 +1222,8 @@ struct security_operations { int (*inode_readlink) (struct dentry *dentry); int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd); int (*inode_permission) (struct inode *inode, int mask, struct nameidata *nd); - int (*inode_setattr)(struct dentry *dentry, struct iattr *attr); + int (*inode_setattr) (struct dentry *dentry, struct vfsmount *mnt, + struct iattr *attr); int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry); void (*inode_delete) (struct inode *inode); int (*inode_setxattr) (struct dentry *dentry, char *name, void *value, @@ -1708,11 +1710,12 @@ static inline int security_inode_permiss } static inline int security_inode_setattr (struct dentry *dentry, + struct vfsmount *mnt, struct iattr *attr) { if (unlikely (IS_PRIVATE (dentry-d_inode))) return 0; - return security_ops-inode_setattr (dentry, attr); + return security_ops-inode_setattr (dentry, mnt, attr); } static inline int security_inode_getattr (struct vfsmount *mnt, @@ -2412,6 +2415,7 @@ static inline int security_inode_permiss } static inline int security_inode_setattr (struct dentry *dentry, + struct vfsmount *mnt, struct iattr *attr) { return 0; --- a/security/dummy.c +++ b/security/dummy.c @@ -328,7 +328,8 @@ static int dummy_inode_permission (struc return 0; } -static int dummy_inode_setattr (struct dentry *dentry, struct iattr *iattr) +static int dummy_inode_setattr (struct dentry *dentry, struct vfsmount *mnt, + struct iattr *iattr) { return 0; } --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2267,11 +2267,12 @@ static int selinux_inode_permission(stru file_mask_to_av(inode-i_mode, mask), NULL); } -static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) +static int selinux_inode_setattr(struct dentry *dentry, struct vfsmount *mnt, +struct iattr *iattr) { int rc; - rc = secondary_ops-inode_setattr(dentry, iattr); + rc = secondary_ops-inode_setattr(dentry, mnt, iattr); if (rc) return rc; -- - 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
[RFD 0/4] AppArmor - Don't pass NULL nameidata to vfs_create/lookup/permission IOPs
-- This post is a request for discussion on creating a second smaller nameidata struct to eliminate conditionally passing of vfsmounts to the LSM. It contains a series of patches that apply on top of the AppArmor patch series. These patches were previously post on May 14, but received no feedback. Any and all feedback is welcome so that we can improve these patches or replace them with a better solution if one presents it self. To remove conditionally passing of vfsmounts to the LSM, a nameidata struct can be instantiated in the nfsd and mqueue filesystems. This however results in useless information being passed down, as not all fields in the nameidata struct will be meaingful. The nameidata struct is split creating struct nameidata2 that contains only the fields that will carry meaningful information. The creation of the nameidata2 struct raises the possibility of replacing the current dentry, vfsmount argument pairs in the vfs and lsm patches with a single nameidata2 argument although these patches do not currently do this. A tarball of these patches and the AppArmor kernel patches are available at: http://forgeftp.novell.com//apparmor/LKML_Submission-June-07/ - 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
[RFD 2/4] Never pass a NULL nameidata to vfs_create()
Create a nameidata2 struct in nfsd and mqueue so that vfs_create does need to conditionally pass the vfsmnt. Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] --- fs/namei.c|2 +- fs/nfsd/vfs.c | 42 +- ipc/mqueue.c |7 ++- 3 files changed, 32 insertions(+), 19 deletions(-) --- a/fs/namei.c +++ b/fs/namei.c @@ -1532,7 +1532,7 @@ int vfs_create(struct inode *dir, struct return -EACCES; /* shouldn't it be ENOSYS? */ mode = S_IALLUGO; mode |= S_IFREG; - error = security_inode_create(dir, dentry, nd ? nd-mnt : NULL, mode); + error = security_inode_create(dir, dentry, nd-mnt, mode); if (error) return error; DQUOT_INIT(dir); --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1121,7 +1121,8 @@ nfsd_create(struct svc_rqst *rqstp, stru char *fname, int flen, struct iattr *iap, int type, dev_t rdev, struct svc_fh *resfhp) { - struct dentry *dentry, *dchild = NULL; + struct nameidata2 nd; + struct dentry *dchild = NULL; struct svc_export *exp; struct inode*dirp; __be32 err; @@ -1138,9 +1139,11 @@ nfsd_create(struct svc_rqst *rqstp, stru if (err) goto out; - dentry = fhp-fh_dentry; + nd.dentry = fhp-fh_dentry; exp = fhp-fh_export; - dirp = dentry-d_inode; + nd.mnt = exp-ex_mnt; + nd.flags = 0; + dirp = nd.dentry-d_inode; err = nfserr_notdir; if(!dirp-i_op || !dirp-i_op-lookup) @@ -1152,7 +1155,7 @@ nfsd_create(struct svc_rqst *rqstp, stru if (!resfhp-fh_dentry) { /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */ fh_lock_nested(fhp, I_MUTEX_PARENT); - dchild = lookup_one_len(fname, dentry, flen); + dchild = lookup_one_len(fname, nd.dentry, flen); host_err = PTR_ERR(dchild); if (IS_ERR(dchild)) goto out_nfserr; @@ -1166,8 +1169,8 @@ nfsd_create(struct svc_rqst *rqstp, stru /* not actually possible */ printk(KERN_ERR nfsd_create: parent %s/%s not locked!\n, - dentry-d_parent-d_name.name, - dentry-d_name.name); + nd.dentry-d_parent-d_name.name, + nd.dentry-d_name.name); err = nfserr_io; goto out; } @@ -1178,7 +1181,7 @@ nfsd_create(struct svc_rqst *rqstp, stru err = nfserr_exist; if (dchild-d_inode) { dprintk(nfsd_create: dentry %s/%s not negative!\n, - dentry-d_name.name, dchild-d_name.name); + nd.dentry-d_name.name, dchild-d_name.name); goto out; } @@ -1192,7 +1195,7 @@ nfsd_create(struct svc_rqst *rqstp, stru err = 0; switch (type) { case S_IFREG: - host_err = vfs_create(dirp, dchild, iap-ia_mode, NULL); + host_err = vfs_create(nd.dentry-d_inode, dchild, iap-ia_mode, nd); break; case S_IFDIR: host_err = vfs_mkdir(dirp, dchild, exp-ex_mnt, iap-ia_mode); @@ -1212,7 +1215,7 @@ nfsd_create(struct svc_rqst *rqstp, stru goto out_nfserr; if (EX_ISSYNC(exp)) { - err = nfserrno(nfsd_sync_dir(dentry)); + err = nfserrno(nfsd_sync_dir(nd.dentry)); write_inode_now(dchild-d_inode, 1); } @@ -1252,7 +1255,9 @@ nfsd_create_v3(struct svc_rqst *rqstp, s struct svc_fh *resfhp, int createmode, u32 *verifier, int *truncp, int *created) { - struct dentry *dentry, *dchild = NULL; + struct nameidata2 nd; + struct dentry *dchild = NULL; + struct svc_export *exp; struct inode*dirp; __be32 err; int host_err; @@ -1270,8 +1275,11 @@ nfsd_create_v3(struct svc_rqst *rqstp, s if (err) goto out; - dentry = fhp-fh_dentry; - dirp = dentry-d_inode; + nd.dentry = fhp-fh_dentry; + exp = fhp-fh_export; + nd.mnt = exp-ex_mnt; + nd.flags = 0; + dirp = nd.dentry-d_inode; /* Get all the sanity checks out of the way before * we lock the parent. */ @@ -1283,12 +1291,12 @@ nfsd_create_v3(struct svc_rqst *rqstp, s /* * Compose the response file handle. */ - dchild = lookup_one_len(fname, dentry, flen); + dchild = lookup_one_len(fname, nd.dentry, flen); host_err = PTR_ERR(dchild); if (IS_ERR(dchild)) goto out_nfserr; - err = fh_compose(resfhp, fhp-fh_export, dchild, fhp); +
[RFD 4/4] Pass nameidata2 to permission() from nfsd_permission()
Construct a nameidata object and pass it down to permission(), so that we can do the proper mount flag checks there. Note that confining nfsd with AppArmor makes no sense, and so this patch is not necessary for AppArmor alone. Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] --- fs/nfsd/vfs.c |9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1804,6 +1804,7 @@ nfsd_statfs(struct svc_rqst *rqstp, stru __be32 nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc) { + struct nameidata2 nd; struct inode*inode = dentry-d_inode; int err; @@ -1869,12 +1870,16 @@ nfsd_permission(struct svc_export *exp, inode-i_uid == current-fsuid) return 0; - err = permission(inode, acc (MAY_READ|MAY_WRITE|MAY_EXEC), NULL); + nd.dentry = dentry; + nd.mnt = exp-ex_mnt; + nd.flags = LOOKUP_ACCESS; + + err = permission(inode, acc (MAY_READ|MAY_WRITE|MAY_EXEC), nd); /* Allow read access to binaries even when mode 111 */ if (err == -EACCES S_ISREG(inode-i_mode) acc == (MAY_READ | MAY_OWNER_OVERRIDE)) - err = permission(inode, MAY_EXEC, NULL); + err = permission(inode, MAY_EXEC, nd); return err? nfserrno(err) : 0; } -- - 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: [AppArmor 00/44] AppArmor security module overview
On Tue, 26 Jun 2007 16:07:56 -0700 [EMAIL PROTECTED] wrote: This post contains patches to include the AppArmor application security framework, with request for inclusion into -mm for wider testing. Patches 24 and 31 didn't come through. Rolled-up diffstat (excluding 2431): fs/attr.c|7 fs/dcache.c | 181 ++- fs/ecryptfs/inode.c | 41 fs/exec.c|3 fs/fat/file.c|2 fs/hpfs/namei.c |2 fs/namei.c | 115 +- fs/nfsd/nfs4recover.c|7 fs/nfsd/nfs4xdr.c|2 fs/nfsd/vfs.c| 89 + fs/ntfs/file.c |2 fs/open.c| 50 fs/reiserfs/file.c |2 fs/reiserfs/xattr.c |8 fs/splice.c |4 fs/stat.c|2 fs/sysfs/file.c |2 fs/utimes.c | 11 fs/xattr.c | 75 - fs/xfs/linux-2.6/xfs_lrw.c |2 include/linux/audit.h| 12 include/linux/fs.h | 27 include/linux/nfsd/nfsd.h|3 include/linux/security.h | 182 ++- include/linux/sysctl.h |2 include/linux/xattr.h| 11 ipc/mqueue.c |2 kernel/audit.c |6 kernel/sysctl.c | 27 mm/filemap.c | 12 mm/filemap_xip.c |2 mm/shmem.c |2 mm/tiny-shmem.c |2 net/unix/af_unix.c |2 security/Kconfig |1 security/Makefile|1 security/apparmor/Kconfig| 10 security/apparmor/Makefile | 13 security/apparmor/apparmor.h | 265 + security/apparmor/apparmorfs.c | 252 + security/apparmor/inline.h | 211 security/apparmor/list.c | 94 + security/apparmor/locking.txt| 68 + security/apparmor/lsm.c | 817 security/apparmor/main.c | 1255 + security/apparmor/match.c| 248 security/apparmor/match.h| 83 + security/apparmor/module_interface.c | 589 +++ security/apparmor/procattr.c | 155 +++ security/commoncap.c |7 security/dummy.c | 43 security/selinux/hooks.c | 94 - 52 files changed, 4701 insertions(+), 404 deletions(-) which seems OK. so... where do we stand with this? Fundamental, irreconcilable differences over the use of pathname-based security? Are there any other sticking points? - 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 try #2] security: Convert LSM into a static interface
On Jun 26, 2007, at 09:47:12, Serge E. Hallyn wrote: Quoting Kyle Moffett ([EMAIL PROTECTED]): On Jun 25, 2007, at 16:37:58, Andreas Gruenbacher wrote: It's useful for some LSMs to be modular, and LSMs which are y/n options won't have any security architecture issues with unloading at all. The mere fact that SELinux cannot be built as a module is a rather weak argument for disabling LSM modules as a whole, so please don't. Here are a few questions for you: 1) What do you expect to happen to all the megs of security data when you rmmod selinux? Read the sentence right above yours again. Noone is saying we should be able to rmmod selinux. Ok, so say we extend LSM to do what AppArmor or TOMOYO need, what do you expect to happen when you rmmod tomoyo, rmmod apparmor, or whatever? Each of those is also going to stick lots of context on various objects during the course of running, the same way that the VM subsystem sticks lots of context on filesystem pages while running. Besides, even the standard capabilities module wants to attach a list of capabilities to every process and defines inheritance rules for them. Ergo you have the problems described below: Do you maintain a massive linked list of security data (with all the locking and performance problems) so that you can iterate over it calling kfree()? What synchronization primitive do we have right now which could safely stop all CPUs outside of security calls while we NULL out and free security data and disable security operations? Don't say software suspend and process freezer, since those have whole order-of-magnitude-complexity problems of their own (and don't always work right either). 2) When you modprobe my_custom_security_module, how exactly do you expect that all the processes, files, shared memory segments, file descriptors, sockets, SYSV mutexes, packets, etc will get appropriate security pointers? Those don't all need labels for capabilities, for instance. This question is as wrong as the last one. Ok, so let's just restrict ourselves to the simple dumb-as-dirt capabilities module. Every process is labeled with capabilities while running under that LSM, right? What happens when you rmmod capabilities? Do you iterate over all the processes to remove their security data even while they may be using it? Or do you just let it leak? Some daemons test if capabilities are supported, and if so they modify their capability set instead of forking a high-priv and a low-priv process and doing IPC. When you remove the capabilities module, suddenly all those programs will lose that critical low- privilege data and become full root. What happens later when you modprobe capabilities? Do you suddenly have to stop the system while you iterate over EVERY process to set capabilities based on whether it's root or not? It's also impossible to determine from a given state in time what processes should have capabilities, as the model includes inheritance, which includes processes that don't even exist anymore. 3) This sounds suspiciously like The mere fact that the Linux-2.6-VM cannot be built as a module is a rather weak argument for disabling VFS modules as a whole. No, your argument sounds like my fs can't be a module so neither should any. Let's go over the differences between my fs and my LSM, and the similarities between my VM and my LSM: Filesystems don't get hooked from virtually every userspace-initiated operation, whereas both VMs and LSMs do. VMs and LSMs attach anonymous state data to a large percentage of the allocated objects in the system, whereas filesystems allocate their own independent datastructure and use that. Would you want to rmmod ext3 and then modprobe ext2 while you have an ext2-as-ext3 filesystem *mounted*??? If you want a good analogy, that's a better one than the my fs can't be a module crap. This whole discussion boils down to 2 points: 1) As currently implemented, no LSM may be safely rmmod-ed 2) Someone has submitted a patch which fixes that problem (you can't rmmod them at all, so no crashes) If you really want to do modular LSMs, then you need to submit a patch which fixes all the race conditions in LSM removal *without* adding much extra overhead. I'm sure if your solutions works then everyone will be much more open to modular LSMs. I said this before: So... Do you have a proposal for solving those rather fundamental design gotchas? If so, I'm sure everybody here would love to see your patch Cheers, Kyle Moffett - 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: [RFD 1/4] Pass no useless nameidata to the create, lookup, and permission IOPs
In message [EMAIL PROTECTED], [EMAIL PROTECTED] writes: The create, lookup, and permission inode operations are all passed a full nameidata. This is unfortunate because in nfsd and the mqueue filesystem, we must instantiate a struct nameidata but cannot provide all of the same information that a regular lookup would provide. The unused fields take up space on the stack, but more importantly, it is not obvious which fields have meaningful values and which don't, and so things might easily break. This patch introduces struct nameidata2 with only the fields that make sense independent of an actual lookup, and uses that struct in those places where a full nameidat is not needed. I agree w/ Trond that a better name is needed other than 'nameidata2', esp. for something that's a sub-structure (perhaps start it with a '__'?) These changes would probably help stackable file systems (e.g., eCryptfs and esp. Unionfs) a lot, b/c stackable f/s often call the lower f/s to lookup files and such; and in most cases, we just need to pass the intent down, not the full VFS-level state info. +/** + * Fields shared between nameidata and nameidata2 -- nameidata2 could + * simply be embedded in nameidata, but then the vfs code would become + * cluttered with dereferences. + */ +#define __NAMEIDATA2 \ + struct dentry *dentry;\ + struct vfsmount *mnt; \ + unsigned intflags; \ + \ + union { \ + struct open_intent open;\ + } intent; Perhaps it is also time to put the dentry + mnt into a single struct path? It's a small change, but it emphasizes that the two items here, dentry+mnt, really define a single path to be passed around: #define __NAMEIDATA \ struct path path; \ unsigned int flags; \ ... Of course, you'll have to change instances of nd-dentry to nd-path.dentry and so on. Erez. - 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 try #2] security: Convert LSM into a static interface
Kyle Moffett wrote: Let's go over the differences between my fs and my LSM, and the similarities between my VM and my LSM: Filesystems don't get hooked from virtually every userspace-initiated operation, whereas both VMs and LSMs do. VMs and LSMs attach anonymous state data to a large percentage of the allocated objects in the system, whereas filesystems allocate their own independent datastructure and use that. Would you want to rmmod ext3 and then modprobe ext2 while you have an ext2-as-ext3 filesystem *mounted*??? If you want a good analogy, that's a better one than the my fs can't be a module crap. This whole discussion boils down to 2 points: 1) As currently implemented, no LSM may be safely rmmod-ed 2) Someone has submitted a patch which fixes that problem (you can't rmmod them at all, so no crashes) If you really want to do modular LSMs, then you need to submit a patch which fixes all the race conditions in LSM removal *without* adding much extra overhead. I'm sure if your solutions works then everyone will be much more open to modular LSMs. I said this before: Hmmm. You seem to be mostly concerned with safely rmmod'ing modules. In contrast, my main concern with the proposed patch is that it removes the ability to *insert* a module. Consider the use case of joe admin who is running enterprise-supported RHEL or SLES, and wants to try some newfangled LSM FooSecureMod thingie. So he grabs a machine, config's selinux=0 or apparmor=0 and loads his own module on boot, and plays with it. He even likes FooSecure, better than SELinux or AppArmor, and wants to roll it out across his data center. Without James's patch, he can do that, and at worst has a tainted kernel. RH or Novell or his favorite distro vendor can fix that with a wave of the hand and bless FooSecure as a module. With James's patch, he has to patch his kernels, and then enterprise support is hopeless, to say nothing of the barrier to entry that patch and rebuild kernel is more than many admins are willing to do. So to solve the problem James Kyle are concerned with, and preserve user choice, how about we *only* remove the ability to rmmod, and leave in place the ability to modprobe? Or even easier, LSMs that don't want to be unloaded can just block rmmod, and simple LSMs that can be unloaded safely can permit it. Crispin -- Crispin Cowan, Ph.D. http://crispincowan.com/~crispin/ Director of Software Engineering http://novell.com AppArmor Chat: irc.oftc.net/#apparmor - 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
[AppArmor 24/44] Pass struct vfsmount to the inode_getxattr LSM hook
This is needed for computing pathnames in the AppArmor LSM. Signed-off-by: Tony Jones [EMAIL PROTECTED] Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED] Signed-off-by: John Johansen [EMAIL PROTECTED] --- fs/xattr.c |2 +- include/linux/security.h | 13 - security/dummy.c |3 ++- security/selinux/hooks.c |3 ++- 4 files changed, 13 insertions(+), 8 deletions(-) --- a/fs/xattr.c +++ b/fs/xattr.c @@ -116,7 +116,7 @@ vfs_getxattr(struct dentry *dentry, stru if (error) return error; - error = security_inode_getxattr(dentry, name); + error = security_inode_getxattr(dentry, mnt, name); if (error) return error; --- a/include/linux/security.h +++ b/include/linux/security.h @@ -391,7 +391,7 @@ struct request_sock; * @value identified by @name for @dentry and @mnt. * @inode_getxattr: * Check permission before obtaining the extended attributes - * identified by @name for @dentry. + * identified by @name for @dentry and @mnt. * Return 0 if permission is granted. * @inode_listxattr: * Check permission before obtaining the list of extended attribute @@ -1248,7 +1248,8 @@ struct security_operations { struct vfsmount *mnt, char *name, void *value, size_t size, int flags); - int (*inode_getxattr) (struct dentry *dentry, char *name); + int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt, + char *name); int (*inode_listxattr) (struct dentry *dentry); int (*inode_removexattr) (struct dentry *dentry, char *name); const char *(*inode_xattr_getsuffix) (void); @@ -1782,11 +1783,12 @@ static inline void security_inode_post_s security_ops-inode_post_setxattr (dentry, mnt, name, value, size, flags); } -static inline int security_inode_getxattr (struct dentry *dentry, char *name) +static inline int security_inode_getxattr (struct dentry *dentry, + struct vfsmount *mnt, char *name) { if (unlikely (IS_PRIVATE (dentry-d_inode))) return 0; - return security_ops-inode_getxattr (dentry, name); + return security_ops-inode_getxattr (dentry, mnt, name); } static inline int security_inode_listxattr (struct dentry *dentry) @@ -2487,7 +2489,8 @@ static inline void security_inode_post_s int flags) { } -static inline int security_inode_getxattr (struct dentry *dentry, char *name) +static inline int security_inode_getxattr (struct dentry *dentry, + struct vfsmount *mnt, char *name) { return 0; } --- a/security/dummy.c +++ b/security/dummy.c @@ -368,7 +368,8 @@ static void dummy_inode_post_setxattr (s { } -static int dummy_inode_getxattr (struct dentry *dentry, char *name) +static int dummy_inode_getxattr (struct dentry *dentry, + struct vfsmount *mnt, char *name) { return 0; } --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2393,7 +2393,8 @@ static void selinux_inode_post_setxattr( return; } -static int selinux_inode_getxattr (struct dentry *dentry, char *name) +static int selinux_inode_getxattr (struct dentry *dentry, struct vfsmount *mnt, + char *name) { return dentry_has_perm(current, NULL, dentry, FILE__GETATTR); } -- - 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 try #2] security: Convert LSM into a static interface
On Jun 26, 2007, at 20:57:53, Crispin Cowan wrote: Kyle Moffett wrote: Let's go over the differences between my fs and my LSM, and the similarities between my VM and my LSM: Filesystems don't get hooked from virtually every userspace-initiated operation, whereas both VMs and LSMs do. VMs and LSMs attach anonymous state data to a large percentage of the allocated objects in the system, whereas filesystems allocate their own independent datastructure and use that. Would you want to rmmod ext3 and then modprobe ext2 while you have an ext2-as-ext3 filesystem *mounted*??? If you want a good analogy, that's a better one than the my fs can't be a module crap. This whole discussion boils down to 2 points: 1) As currently implemented, no LSM may be safely rmmod-ed 2) Someone has submitted a patch which fixes that problem (you can't rmmod them at all, so no crashes) If you really want to do modular LSMs, then you need to submit a patch which fixes all the race conditions in LSM removal *without* adding much extra overhead. I'm sure if your solutions works then everyone will be much more open to modular LSMs. Hmmm. You seem to be mostly concerned with safely rmmod'ing modules. In contrast, my main concern with the proposed patch is that it removes the ability to *insert* a module. You must have missed this in my emails: 2) When you modprobe my_custom_security_module, how exactly do you expect that all the processes, files, shared memory segments, file descriptors, sockets, SYSV mutexes, packets, etc will get appropriate security pointers? This isn't even solvable the same way the rmmod problem is, since most of that isn't even accessible without iterating over the ENTIRE dcache, icache, every process, every process' file-descriptors, every socket, every unix socket, every anonymous socket, every SYSV shm object, every currently-in-process packet. I'd argue that security-module-insertion is actually MORE complicated than removal. Here's one example: TOMOYO cares about the process execution tree, but you can't penalize the no-LSM case by a percent or two to add that kind of data. When TOMOYO is loaded, it wants to do access control based on process execution trees for which data DOES NOT EXIST!!! Not only that, but the processes which originally ran the one you care about (and which you'd need to recreate that data) may have exited anywhere from seconds to years before. It is fundamentally IMPOSSIBLE to recreate that data, even if you could solve the problems of how to do it while the system is running without racing with existing process operations. Imagine a process which hasn't had security data tagged to it yet which opens thousands of FIFOs per second, waits for your tagging code to assign security data to them in the filesystem, and then removes them; if you did it right you could prevent the code from EVER completely tagging every object (even assuming you could recreate enough information). Such a need to add extra security data to multiple classes of objects is *fundamental* to any security module (isn't that the whole point?) As such, you can't just modprobe one and expect it to work. That's like mounting an ext2 filesystem, and then later trying to modprobe ext3 and dynamically switch to the ext3 code and enable journalling all at once ON THE MOUNTED FILESYSTEM!!! Sure, theoretically it *could* be done, but the code complexity is hardly worth it (plus nobody has yet even tried posting patches to make it happen). Consider the use case of joe admin who is running enterprise- supported RHEL or SLES, and wants to try some newfangled LSM FooSecureMod thingie. So he grabs a machine, config's selinux=0 or apparmor=0 and loads his own module on boot, and plays with it. He even likes FooSecure, better than SELinux or AppArmor, and wants to roll it out across his data center. Flatly impossible. You simply cannot load a security module and hope to provide any useful information about the system's present state. If you want comprehensive security it has to be there before a single byte of userspace code is executed. SELinux sort-of handles unlabelled objects by treating them with a small set of initial types, but that's only enough to get the system up enough to actually relabel objects with type-transitions (after init loads the selinux policy it reexecs itself, before doing anything else). So to solve the problem James Kyle are concerned with, and preserve user choice, how about we *only* remove the ability to rmmod, and leave in place the ability to modprobe? Or even easier, LSMs that don't want to be unloaded can just block rmmod, and simple LSMs that can be unloaded safely can permit it. An LSM simple enough to unload would be too simple for anybody to want to load in the first place (even capabilities can have this problem). What kind of
Re: [AppArmor 00/44] AppArmor security module overview
On Tue, 26 Jun 2007 19:24:03 -0700 John Johansen [EMAIL PROTECTED] wrote: so... where do we stand with this? Fundamental, irreconcilable differences over the use of pathname-based security? There certainly seems to be some differences of opinion over the use of pathname-based-security. I was refreshed to have not been cc'ed on a lkml thread for once. I guess it couldn't last. Do you agree with the irreconcilable part? I think I do. I suspect that we're at the stage of having to decide between a) set aside the technical issues and grudgingly merge this stuff as a service to Suse and to their users (both of which entities are very important to us) and leave it all as an object lesson in how-not-to-develop-kernel-features. Minimisation of the impact on the rest of the kernel is of course very important here. versus b) leave it out and require that Suse wear the permanent cost and quality impact of maintaining it out-of-tree. It will still be an object lesson in how-not-to-develop-kernel-features. Sigh. Please don't put us in this position again. Get stuff upstream before shipping it to customers, OK? It ain't rocket science. Are there any other sticking points? The conditional passing of the vfsmnt mount in the vfs, as done in this patch series, has received a NAK. This problem results from NFS passing a NULL nameidata into the vfs. We have a second patch series that we have posted for discussion that addresses this by splitting the nameidata struct. Message-Id: [EMAIL PROTECTED] Subject: [RFD 0/4] AppArmor - Don't pass NULL nameidata to vfs_create/lookup/permission IOPs other issues that have been raised are: - AppArmor does not currently mediate IPC and network communications. Mediation of these is a wip - the use of d_path to generate the pathname used for mediation when a file is opened. - Generating the pathname using a reverse walk is considered ugly - A buffer is alloced to store the generated path name. - The buffer size has a configurable upper limit which will cause opens to fail if the pathname length exceeds this limit. This is a fail closed behavior. - there have been some concerns expressed about the performance of this approach We are evaluating our options on how best to address this issue. OK, useful summary, thanks. I'd encourage you to proceed apace. - 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 try #2] security: Convert LSM into a static interface
* Crispin Cowan ([EMAIL PROTECTED]) wrote: and simple LSMs that can be unloaded safely can permit it. there are none, and making the above possible is prohibitively expensive. - 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