2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-31 22:35:35 +00:00

Compare commits

...

109 Commits

Author SHA1 Message Date
Steve Beattie
6f82124e52 Adjust clean target to match trunk. 2011-02-16 09:40:07 -08:00
Steve Beattie
d3989823ca toplevel makefile:
- adjust snapshot version to be less than the upcoming version
- add a tag target
- be a little more paranoid in the clean target and adjust for snapshot
  versioning scheme.
2011-02-16 09:35:55 -08:00
Steve Beattie
81dac29f52 Prep for 2.5.2 release 2011-02-16 00:12:38 -08:00
Steve Beattie
aeff455da5 Merge from trunk revisions 1519 and 1619: Add the compatibility patches
for the 2.6.36, 2.6.36.2 and 2.6.37 upstream kernel version of
AppArmor.

Nominated-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-02-15 23:11:03 -08:00
Steve Beattie
01b7969eee From: Jeff Mahoney <jeffm@suse.com>
Subject: apparmor-utils: Inherit flags in sub-profiles when generating profiles
References: bnc#496204

 When creating profiles with cx subprofiles, genprof will set the
 sub-profile in enforce mode. When genprof cycles multiple times, it
 prohibits the sub-profile from working correctly.

 e.g.

 # Last Modified: Mon Jan 24 13:52:26 2011
 #include <tunables/global>

 /home/jeffm/mycat flags=(complain) {
   #include <abstractions/base>
   #include <abstractions/bash>
   #include <abstractions/consoles>

   /bin/bash ix,
   /bin/cat cx,
   /home/jeffm/mycat r,

 profile /bin/cat {
     #include <abstractions/base>

     /bin/cat r,
     /home/jeffm/mycat r,

   }
 }

 This patch allows sub-profiles to inherit the flags from the parent
 profile, which allows it to be created in complain mode (if appropriate).
 The temporary complain flags are cleaned up at genprof completion as
 expected.

 This issue was reported at: https://bugzilla.novell.com/show_bug.cgi?id=496204

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>

Bug: https://launchpad.net/bugs/707092
2011-02-15 16:24:33 -08:00
Steve Beattie
8db18e6eb7 From: Jeff Mahoney <jeffm@suse.com>
Subject: Subdomain.pm: Fix for null path
References: bnc#407959

When handling the following log entry, logprof will spew perl errors and
ultimately generate an invalid config: "r,"

Since there is nothing to do with a null path, just skip to the next entry.

type=APPARMOR_DENIED msg=audit(1214497030.421:39): operation="inode_permission" info="Failed name resolution - object not a valid entry" requested_mask="r" denied_mask="r" pid=31367 profile="/usr/sbin/httpd2-worker

Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-02-15 14:42:10 -08:00
Steve Beattie
5e5d91ba76 From: Jeff Mahoney <jeffm@suse.com>
Subject: apparmor: Subdomain.pm: Fix handling of audits of unconfined processes

 The version of AppArmor that was accepted into the mainline kernel
 issues audit events for things like change_hat while unconfined.
 Previous versions just returned -EPERM without the audit.

 This results in logprof and friends spewing uninitialized value errors
 when it hits events like:
 type=AVC msg=audit(1291742101.899:220): apparmor="DENIED" operation="change_hat" info="unconfined" error=-1 pid=28005 comm="cron

 ... which happen any time an unconfined process does something with pam
 when pam_apparmor is installed.

 This patch skips those events.

[Note that the second half of the OpenSUSE patch had already been applied.]

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-02-15 11:14:15 -08:00
Steve Beattie
1d43cdae44 From: Jeff Mahoney <jeffm@suse.com>
Subject: apparmor-profiles: Fix proc usage in firefox profile
References: bnc#436262

 This patch corrects the use of the {proc} macro. It should be {PROC}.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-02-15 11:01:55 -08:00
Steve Beattie
bd6e9dcb9e From: Jeff Mahoney <jeffm@suse.com>
Subject: apparmor: Fix incorrect /proc/*/sys usage in usr.sbin.ntpd
References: bnc#634801

 /proc/sys/kernel exists, but /proc/*/sys/kernel doesn't. This patch
 fixes the profile.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-02-15 10:50:16 -08:00
Steve Beattie
955404ca00 Author: Jamie Strandboge <jamie@canonical.com>
Description: the Ubuntu buildds do not have the AppArmor securityfs mounted, so
 the cache tests fail. This patch skips these tests if the introspection
 directory is not mounted, but runs them if it is. This should allow testing of
 local builds while still allowing builds on the official buildds.

Acked-By: Steve Beattie <sbeattie@ubuntu.com> - both Ubuntu and
OpenSUSE were carrying patches that disabled the caching test,
though OpenSUSE's disabled it completely rather than checking. The
parser builds need to complete even when the kernel it's building on
doesn't support AppArmor or all the extensions that the parser needs
at runtime.
2011-02-15 10:34:17 -08:00
Steve Beattie
5425aadb6d From: Jeff Mahoney <jeffm@suse.com>
Subject: apparmor-utils: Translation unification
References: bnc#586072

 This patch removes small inconsistencies between identical strings to
 allow for easier translation.

Reported-by: Isis Binder <isis.binder@gmail.com>
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-02-08 16:19:25 -08:00
Steve Beattie
08df8d93ce Merge from trunk rev 1644: Purge utils/severity.pl due to incorrect
license/copyright statement. It should have been covered under both
the Immunix acquisition by Novell Inc and by the open sourcing of
the apparmor tree by Novell Inc.
2011-02-08 15:56:43 -08:00
Steve Beattie
34c013f036 From: Jeff Mahoney <jeffm@suse.com>
Subject: [PATCH] apparmor-utils: cleanup after abort in genprof
References: bnc#307067

 The initial generation of the base profile is required to be written out
 to put the process in complain mode for observation. If the user
 decides to abort the profiling session, that base profile is left
 behind.

 This patch removes all profiles created during the run up to an abort.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-02-08 14:49:32 -08:00
Steve Beattie
ab927317e5 Merge from trunk rev 1639: Fix compilation in deprecated gnome
apparmor applet.

Nominated-by: Jeff Mahoney <jeffm@suse.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-02-08 13:20:05 -08:00
Steve Beattie
c1dacca6c7 From: Jeff Mahoney <jeffm@suse.com>
utils/Makefile: abstract out the perl vendor location for distros to
override if necessary

Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-02-08 10:35:10 -08:00
Steve Beattie
aa024ec29c From: Jeff Mahoney <jeffm@suse.com>
Fix grammar in in utils UI text.
2011-02-08 10:23:11 -08:00
Steve Beattie
829e75b2e2 Merge from trunk rev 1636: libapparmor: remove LD_RUN_PATH from swig
generated makefile as it results in an rpath binding in the library.

Nominated-by: Jeff Mahoney <jeffm@suse.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-02-08 09:48:57 -08:00
Steve Beattie
b5754812f0 Makefile: make setup target work independently. 2011-02-08 09:32:16 -08:00
Steve Beattie
3cb964c5ee Subject: logprof - variable definitions should not have trailing commas.
This patch fixes a logprof bug where when profiles with variable
declarations at the top level (not hidden in an include) were written
back to a file, a trailing comma was being added to the declaration
statement, which is invalid apparmor policy syntax. This patch corrects
this and no longer adds the trailing comma.
2011-02-04 21:16:20 -08:00
Steve Beattie
05450ac38a From: Jeff Mahoney <jeffm@suse.com>
Subject: apparmor: Fix network event parsing
References: bnc#665483

 The upstream version of AppArmor had network mediation but it was
 removed. There's a compability patch floating around that both openSUSE
 and Ubuntu have applied to their kernels. Unfortunately, one part was
 overlooked. The socket operation event names where changed from the
 socket_ prefixed names they had when AppArmor was out-of-tree and
 utils/SubDomain.pm was never updated to understand them.

 This patch adds an operation-type table so that the code can just
 do a optype($operation) call to discover what type of operation a
 particular name refers to. It then uses this in place of the socket_
 checks to decide whether an event is a network operation.

 This allows genprof and logprof to work with networking rules again.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>


Bug: https://launchpad.net/bugs/706733
2011-01-24 15:09:08 -08:00
Steve Beattie
d788ceb928 From: Jeff Mahoney <jeffm@suse.com>
Subject: apparmor-parser: Fix up translations
References: bnc#586070

Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-14 17:43:44 -06:00
Steve Beattie
c1a11fb8b6 Merge from trunk revision 1572: This patch fixes the parser's lexer to
not passthrough other invalid characters in variable declarations. It
also adds testcases demonstrating the issue.

Nominated-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-14 16:55:20 -06:00
Steve Beattie
d7e06b79bb Merge from trunk revision 1571: This patch fixes the parser to return
an error when variable declaration statements contain trailing commas,
instead of passing them through to STDOUT. It also adds parser
testcases demonstrating the issue.

Nominated-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-14 16:53:51 -06:00
Steve Beattie
7714b62889 Merge from trunk revision 1620: Attached is an updated dnsmasq profile
that fixes the following:
- allow net_admin capability for DHCP server
- allow net_raw and network inet raw for ICMP pings when used as a DHCP server
- allow read and write access to libvirt pid files for dnsmasq

See the FAQ in the dnsmasq source for details. This fixes
https://launchpad.net/bugs/697239

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-14 11:38:56 -06:00
Steve Beattie
bdb6eb82b6 Merge from trunk revision 1615: abstractions/freedesktop.org updates:
- require owner match for files in @{HOME}
- add new path for @{HOME}/.local/share/recently-used.xbel*
- add the following, confirmed via specifications:
  /usr/share/applications/mimeinfo.cache r,
  /usr/share/applications/*.desktop r,
  owner @{HOME}/.local/share/applications/defaults.list r,
  owner @{HOME}/.local/share/applications/mimeinfo.cache r,
  owner @{HOME}/.local/share/applications/mimeapps.list r,
  owner @{HOME}/.local/share/applications/*.desktop r,

References:
http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-0.9.4.html
http://www.freedesktop.org/wiki/Specifications/mime-actions-spec

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-14 11:35:15 -06:00
Steve Beattie
9142fc482a Merge from trunk revision 1614: abstractions/X: allow access to
/usr/lib32 and /usr/lib64 for dri modules (LP: #658135)

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-14 11:34:12 -06:00
Steve Beattie
1c55cf035c Merge from trunk revision 1613: add enchant abstraction. Enchant is a
frontend for spellcheckers and in use by more and more applications,
including empathy and evolution. It is listed on freedesktop.org. See:
http://www.abisource.com/projects/enchant/

This abstraction gives access to enchant itself, files in the user's
home directory for enchant and various dictionaries for:
  - aspell
  - ispell
  - hunspell
  - myspell
  - hspell
  - zemberek
  - voikko

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-14 11:31:44 -06:00
Steve Beattie
05dfb21b32 Merge from trunk revision 1612: allow 'rw' to /var/log/samba/cores/
(LP: #652562)

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-14 11:30:18 -06:00
Steve Beattie
4f856a0510 Merge from trunk revision 1611: add preliminary ibus abstraction. Will
likely need more once more ibus users start to use it. Additionally,
the 'rw' on the @{HOME}/.config/ibus/bus/ probably only needs 'create'
and 'chmod', so that could be tightened up once those are exposed in
the tools. LP: #649497.

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-14 11:28:30 -06:00
Steve Beattie
0a14cf2849 Merge from trunk revision 1610: abstractions/user-manpages: require
owner match for files in @{HOME} and /tmp

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-14 11:26:42 -06:00
Steve Beattie
fcd150c239 Merge from trunk revision 1609: abstractions/user-mail:
- use character globbing
  - require owner match for files in @{HOME}

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-14 11:25:16 -06:00
Steve Beattie
b33ff8be7f Merge from trunk revision 1608: abstractions/user-write:
- require owner match
  - add @{HOME}/Public/

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-14 11:23:58 -06:00
Steve Beattie
27257d564b Merge from trunk revision 1607: abstractions/user-download:
- fix typo for Desktop (should be Desktop/)
  - require owner match
  - allow writes to @{HOME}/[dD]ownload{,s}

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-14 11:21:38 -06:00
Steve Beattie
793bc2cc01 Merge from trunk revision 1595: add aa_change_profile.pod manpage and
reference it in aa_change_hat.pod

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-13 17:06:58 -06:00
Steve Beattie
4edf5a5a06 Merge from trunk revision 1582: update the man pages to:
* add Canonical to the headers of the pod files touched
    * use aa_change_hat() instead of change_hat() (LP: #692216)
    * use http://wiki.apparmor.net in the SEE ALSO
    * use http://https://bugs.launchpad.net/apparmor/+filebug for bugs
    * prefix 'aa-' in SEE ALSO section for utilities (eg, 'aa-complain'
      for 'complain')

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-13 16:29:20 -06:00
Steve Beattie
0a3c61b75f Merge from trunk revision 1581:
changehat/mod_apparmor/mod_apparmor.pod: make several clarifications
and add a summary for the order of operations

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-13 16:14:17 -06:00
Steve Beattie
ddf1e922d0 Merge from trunk revision 1580: parser/apparmor.d.pod: more fully
document child profiles, including:
    - cx and Cx
    - change_profile()

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-13 16:04:35 -06:00
Steve Beattie
2cc5b3ae70 Merge from trunk revision 1579: apparmor.d.pod: document [^]
Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-13 15:59:27 -06:00
Steve Beattie
e66c163042 Merge from trunk revision 1578: document audit, deny and owner rule
qualifiers (LP: #349049)

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-13 15:58:04 -06:00
Steve Beattie
d34b3d0d7f Merge from trunk revision 1577: mod_apparmor.pod: adjust for Canonical,
launchpad and Ubuntu binaries and tools

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-13 15:55:26 -06:00
Steve Beattie
e638a8b3f4 Merge from trunk revision 1576: parser/apparmor.d.pod: clarify alias rules
Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-13 15:52:12 -06:00
Steve Beattie
5bde5e2fae Merge from trunk revision 1618: add more restrictions to the
private-files and private-files-strict blacklist abstractions.

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-12 13:06:54 -06:00
Steve Beattie
0fb25b57e3 From: Jeff Mahoney <jeffm@suse.com>
Subject: apparmor: Fix use after free in regexp parser

 There are two cases of use-after-free in the simply_tree_base code. It
 worked in the past because there aren't any allocations between the
 free and the use, so it was still around.

 With glibc's memory perturbing feature (set _MALLOC_PERTURB to anything),
 the freed memory is poisoned. This causes crashes in e.g. apparmor_parser
 while parsing certain profiles.

 This patch addresses it by saving a pointer to the node to free after
 the node is advanced.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-07 14:24:24 -08:00
Steve Beattie
93a49944d4 Support newer auditd formatted messages. Patch from mancha on irc.
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-07 13:45:56 -08:00
Steve Beattie
2207e0b264 Fix two x transition conflict bugs.
The is_merged_x_consistend macro was incorrect in that is tested for
USER_EXEC_TYPE to determine if there was an x transition.  This fails
for unconfined execs so an unconfined exec would not correctly conflict
with another exec type.

The dfa match flag table for xtransitions was not large enough and not
indexed properly for pux, and cux transitions.  The index calculation did
not take into account the pux flag so that pux and px aliased to the same
location and cux and cx aliased to the same location.

This would result in the first rule being processed defining what the
transition type was for all following rules of the type following.  So
if a px transition was processed first all pux, transitions in the profile
would be treated pux.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>

Add auto generation of xtransition conflict tests

All the combiniation of xtransition conflics where not well represented in
the regression test suite.  Instead of relying on multiple static test
files, automatically generate all possible conflicts.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-07 12:46:15 -08:00
Steve Beattie
9c3f87c34b Merge from trunk rev 1616: dynamically link in libapparmor library in
libapparmor's testsuite.

From: Jeff Mahoney <jeffm@suse.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-01-05 14:45:17 -08:00
Jamie Strandboge
94e2e19f02 abstractions/ubuntu-browsers: adjust sensible browser to use Pixr 2010-10-22 07:51:57 -05:00
Steve Beattie
59e4883b63 Merge from trunk rev 1390: utils/SubDomain.pm fix warnings for messages
without denied or requested masks.

Nominated-by: Jesse Michael <jesse@lonelyrhinoceros.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-10-11 11:45:28 -07:00
Steve Beattie
9fa6814900 Merge from trunk rev 1514: Have the parser makefile honor CFLAGS
environment variable.

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: John Johansen <john.johansen@canonical.com>
2010-10-09 14:19:13 -07:00
Steve Beattie
a611a0c207 Merge from trunk rev 1505: modifies the xattr regression test to use
a separate loopback mounted filesystem.

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: Jamie Strandboge <jamie@canonical.com>
2010-10-04 12:31:00 -07:00
Steve Beattie
07431af673 Merge from trunk rev 1452: Fixes "deleted" test case to match the
documentation for the expected outcome and add additional positive test.

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: Jamie Strandboge <jamie@canonical.com>
2010-10-04 12:29:46 -07:00
Steve Beattie
513864845e Merge from trunk rev 1442: Fixes several testsuite warnings and typos.
Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: Jamie Strandboge <jamie@canonical.com>
2010-10-04 12:25:06 -07:00
Steve Beattie
9c183302b5 Merge from trunk rev 1388: Break out make targets so that distributors
that don't want full docs can pick targets they want. Comment out
debug dump of generate af_names.h.

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: John Johansen <john.johansen@canonical.com>
2010-09-30 13:28:26 -07:00
Steve Beattie
283f83aafb Merge from trunk rev 1404: fix testsuite autogeneration of profiles on
amd64 systems.

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-09-30 13:16:55 -07:00
Jamie Strandboge
aedac26b32 abstractions/ubuntu-email: adjustment for ever-changing path of thunderbird
(LP: #648900)
2010-09-27 08:48:30 -05:00
Steve Beattie
daa141d65f Merge from trunk rev 1475: fixSubDomain.pm to take truncate, rename_src,
rename_dest, and mkdir operations into account, as well as add
logparsing library testcases for those operations.

Bug: https://bugs.launchpad.net/apparmor/+bug/623467
Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-09-21 00:40:50 -07:00
Steve Beattie
0c8f6e642c Fix minor build warning on rpm based systems. 2010-09-20 11:40:32 -07:00
Steve Beattie
b9172f195d When loading without the 2.4 compatibility patch, the parser needs the
following patch or it will explode when it can't find the "features"
file.

Bug: https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/626984
Nominated-by: Kees Cook <kees@ubuntu.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-09-16 10:13:11 -07:00
Steve Beattie
fc15748264 Fix bzr export command to retain the timestamps from commits, rather
than using the time the export occurred.
2010-09-16 05:37:53 -07:00
Steve Beattie
f86f4cc67c Pull outdated kernel patches, to avoid confusion. Add README to note
that links to the patches will be posted to the wiki and the mailing
list.

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: John Johansen <john.johansen@canonical.com> (on irc)
2010-09-16 02:25:59 -07:00
Steve Beattie
745eebb2b3 Prepare for 2.5.1 rc2 and hopefully final release. 2010-09-15 15:10:42 -07:00
Steve Beattie
266800554b Merge from trunk rev 1501: Reorder the timstamp check to move it to
the beginning of the script and add an additional sleep before the
parser invocation that generates the cache file for the first time.

Submitted-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: Kees Cook <kees@ubuntu.com>
2010-09-15 14:37:53 -07:00
Steve Beattie
be77957326 Merge from trunk revs 1495 and 1496: Update how cache validation is
done to fix the bug where abstraction updates do not cause the cache
file to become invalid.

Nominated-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-09-15 12:01:21 -07:00
Steve Beattie
dba072c530 Merge from trunk rev 1498: Fix write_cache to not be a privileged
operation so that the caching tests can be added to the build. Update
caching tests to detect non-ns-resolution filesystems and back off
on the timing test.

Nominated-by: Kees Cook <kees.cook@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-09-15 11:34:38 -07:00
Steve Beattie
c2109f2c3b Cherry picked elements from trunk commit 1437: fix serious compiler
warnings, silence an error in non-rpm build environs.

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: Kees Cook <kees@ubuntu.com>
2010-09-15 10:24:55 -07:00
Steve Beattie
9578c217cb Much pared down version of trunk commit 1497: fix error checking so that
caching will work without needing kernel_load.

Nominated-by: Kees Cook <kees.cook@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-09-15 09:33:01 -07:00
Jamie Strandboge
24bf1faaac exported smbd files need to have 'k' to work properly with certain applications 2010-09-14 14:17:53 -05:00
Steve Beattie
604b6b10b1 Fix up one little issue with the repo version bit when building outside
of the repo tree.
2010-09-13 01:37:04 -07:00
Steve Beattie
71cda52995 Point the repo target at the correct published tree. 2010-09-12 12:59:05 -07:00
Steve Beattie
2a3967f7f7 Modify the version determining stuff to work with bzr, update the
toplevel tarball make target to create a release tarball and make a
snapshot target to do the same thing for snapshot releases.
2010-09-12 12:56:51 -07:00
Steve Beattie
5308974d27 Preparation for 2.5.1 rc1 release. 2010-09-10 15:11:25 -07:00
Steve Beattie
0c754fe701 Merge from trunk rev 1411: network interface enumeration
Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-09-10 13:19:38 -07:00
Steve Beattie
eeb523ab16 Merge from trunk rev 1410: update for font/icon/mime locations in
current gnome.

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-09-10 13:18:28 -07:00
Steve Beattie
90e414f0ab Merge from trunk rev 1467: Add gdm files to X abstraction.
Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-09-10 13:13:56 -07:00
Jamie Strandboge
6ec327cfb9 tests/regression/subdomain/uservars.inc: apply the uservars.inc change in
trunk's r1458 too
2010-09-10 13:30:25 -05:00
Jamie Strandboge
15f61e5e5b profiles/apparmor.d/abstractions/ubuntu-email: add thunderbird 3
profiles/apparmor.d/abstractions/ubuntu-media-players: add gmplayer
profiles/apparmor.d/abstractions/ubuntu-*: use PUx instead of Ux
2010-09-10 10:28:28 -05:00
Steve Beattie
d4e0f472e2 Merge from trunk rev 1492: add testcases to support previous merges. 2010-09-10 00:46:03 -07:00
Steve Beattie
e89ef114bf Merge from trunk rev 1490: newer apparmor module uses target instead
of name2, add log parsing support for this.

Nominated-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-09-10 00:40:59 -07:00
Steve Beattie
48587d7179 Merge from trunk rev 1489: Status messages have and offset field used
to debug why and where a policy load failed.  For now just ignore it.

Nominated-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-09-10 00:39:16 -07:00
Steve Beattie
8e39e3ab86 Merge from trunk rev 1491: Change the second key_capability entry into
a comment and document why its there and what to do with it once the
old entry types are cleaned up.

Nominated-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-09-10 00:36:33 -07:00
Steve Beattie
fbd1ab065e Merge from trunk rev 1487: Add support for the added capability and
capname fields in LSM_AUDIT records;  For now just use capname and
silently drop capability when it is found.

Nominated-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-09-10 00:33:44 -07:00
Steve Beattie
d41f723645 Merge from trunk rev 1435 (+ creation of empty .err files):
Update log parser grammar to handle new LSM-audit log messages.
Add testcases for new LSM-audit log messages.

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: Kees Cook <kees@ubuntu.com>
2010-09-10 00:18:39 -07:00
Steve Beattie
808bda6792 Merge from trunk rev 1488: handle negative error codes in error= fields.
Nominated-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-09-09 18:38:18 -07:00
Steve Beattie
914f9f5bad Merge from trunk rev 1486: If encountered the scanner will dump
unmatched text from <audit_id>.

Nominated-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-09-09 15:16:36 -07:00
Steve Beattie
cea0cdb4e9 Merge from trunk rev 1485: Fix apparmor_notify memory leak for
non-reported messages.

Nominated-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-09-09 11:28:04 -07:00
Steve Beattie
f12a20dcae Merge of trunk rev 1484: change notify.conf to default to enabling
apparmor_notify.

Nominated-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-09-09 11:25:36 -07:00
Jamie Strandboge
e843ad3457 cherrypick r1483 from trunk:
allow mmap of font cache files in @{HOME}/.fontconfig/ for sun-java6
2010-09-08 13:58:37 -05:00
Jamie Strandboge
9333e221bc update fonts abstraction to add '/var/lib/ghostscript/** r,' 2010-09-03 08:42:29 -05:00
Jamie Strandboge
523738348c merge from trunk: abstractions/ubuntu-browsers: add '/usr/bin/sensible-browser
PUxr'
2010-08-30 11:11:34 -05:00
Steve Beattie
8b79fb5fea Merge from trunk revs 1476, 1477, and 1478: cope with various elements
that the upstream 2.6.36 kernel is missing.

All Nominated-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-08-26 11:24:41 -07:00
Steve Beattie
8878869a0c Modified version of trunk rev 1473:
This teaches pam_apparmor about the current errno returned by the
kernel when the hat that was passed does not exist in the profile (but
other hats exist). (LP: #619521)

It differs to the fix in trunk in that, to be more conservative in
the change, it does not remove the EPERM case, even though it should
not be needed anymore.

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: Kees Cook <kees@ubuntu.com>
2010-08-19 08:45:19 -07:00
Steve Beattie
5fe2fc0c3f Merge from trunk r1462: remove kde4-config from the kde abstraction
Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-08-11 12:06:38 -07:00
Steve Beattie
25f5cc50b3 Merge from trunk r1466: add ca-certificates to ssl_certs abstraction
(LP: #605835)

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-08-11 12:02:36 -07:00
Steve Beattie
72141e5a6e Merge r1457 from trunk: 'owner' match in commit 1406 too strict for
/tmp/ and /var/tmp/ (LP: #615177)

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-08-10 09:12:34 -07:00
Steve Beattie
d323db562a Merge revs 1403, 1417, 1447 from trunk:
* add dbus-session abstraction (and use Pix rather than Uix)
 * fix gnome abstraction for gdk pixbuf loaders (LP: #611248)

Nominated by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-08-05 10:44:08 -07:00
Steve Beattie
030d97e3f1 Merge from r1430: fix for LP: #599450
Changes the table resizing so that there is always sufficient high
entries in the table, preventing bounds violations from occurring.

Nominated-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-07-24 16:16:14 +02:00
Steve Beattie
0eb5d7c050 Merge from r1429: combine the two separate table resize code segments
into a single functionally equivalent segment.

Nominated-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-07-24 16:09:25 +02:00
Steve Beattie
1c1de08f11 Partial merge r1419: add the -p flag to support the output of
flattened profiles.

Submitted-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-07-17 18:39:37 -07:00
Steve Beattie
6dad83c212 Merge r1387: Fix perl swig bindings so that libapparmor can be built
when configured without perl.

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: Marc Deslauriers <marc.deslauriers@canonical.com>
2010-07-13 16:38:39 -07:00
Steve Beattie
1ad455c6da Merge r1385: Fix memory leak during dfa minimization.
Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: Marc Deslauriers <marc.deslauriers@canonical.com>
2010-07-13 16:36:47 -07:00
Steve Beattie
b5c8c2bdaf Merge r1379: Fix leaking file descriptors on included files.
Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: Marc Deslauriers <marc.deslauriers@canonical.com>
2010-07-13 16:31:57 -07:00
Steve Beattie
ac1a585bbe Merge from trunk rev 1424: Move expression tree node labeling into expr
node themselves to reduce memory usage and make node labeling per dfa
rather than global.

Nominated-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-07-12 15:53:51 -07:00
Steve Beattie
8187d02864 Merge in rev 1422 from trunk: Cleaning up the sets firstpos, lastpos,
and followpos early reduces peak memory usage.

Nominated-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-07-12 15:28:26 -07:00
Steve Beattie
8525087270 Merge in r1413 and r1418: report correct filename/line number on errors
in the parser.

r1413 Nominated-by: Kees Cook <kees@ubuntu.com>
r1413 Acked-By: Steve Beattie <sbeattie@ubuntu.com>
r1418 Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
r1418 Acked-By: Kees Cook <kees@ubuntu.com>
r1418 Acked-By: John Johansen <john.johansen@canonical.com>
2010-06-25 12:58:17 -07:00
Steve Beattie
26624648f8 apparmor_notify merges: r1391-r1396,r1401-r1402,r1405,r1407-r1408:
These commits should bring apparmor_notify and apparmor_notify.pod
up to what is in trunk. In short:
- add long options
- cleanup output
- better handle auditd
- handle logfile rotation
- use seteuid() to drop privileges so we can raise/drop after log
  file rotation. Add -u USER option for dropping privileges when not
  using sudo
- man page updates
- group like entries together when using -v with -s (and later cleanups
  including LP: #582075)
Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-06-21 15:36:21 -07:00
Steve Beattie
6f7dad8790 Merge: r1389: add 'k' to /var/lib/samba/**.tdb in the samba abstraction
Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-06-21 15:26:22 -07:00
Steve Beattie
f0d5b09b9f Merge: r1397-r1398: adjust cgi path for php5 abstraction (LP: #538661)
Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-06-21 15:24:35 -07:00
Steve Beattie
ab10eafaaf Merge r1406: abstractions/user-tmp: require 'owner' matching
Nominated-by: Jamie-Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-06-21 15:22:54 -07:00
Steve Beattie
aa106808fd Merge: r1409: statvfs allowed by default
Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2010-06-21 15:21:10 -07:00
569 changed files with 5409 additions and 76489 deletions

1
.bzrignore Normal file
View File

@@ -0,0 +1 @@
parser/tst/simple_tests/generated_x/*.sd

View File

@@ -17,22 +17,40 @@ DIRS=parser \
common \
tests
RELEASE_DIR=apparmor-${VERSION}-${REPO_VERSION}
REPO_URL?=lp:apparmor/2.5
#REPO_URL="bzr+ssh://bazaar.launchpad.net/~sbeattie/apparmor/apparmor-2.5.1-nominations/"
RELEASE_DIR=apparmor-${VERSION}
SNAPSHOT_DIR=apparmor-${VERSION}~${REPO_VERSION}
__SETUP_DIR?=.
.PHONY: tarball
tarball: _dist
tarball: clean
make export_dir __EXPORT_DIR=${RELEASE_DIR}
make setup __SETUP_DIR=${RELEASE_DIR}
tar cvzf ${RELEASE_DIR}.tar.gz ${RELEASE_DIR}
${RELEASE_DIR}:
mkdir ${RELEASE_DIR}
.PHONY: snapshot
snapshot: clean
make export_dir __EXPORT_DIR=${SNAPSHOT_DIR}
make setup __SETUP_DIR=${SNAPSHOT_DIR}
tar cvzf ${SNAPSHOT_DIR}.tar.gz ${SNAPSHOT_DIR}
.PHONY: _dist
.PHONY: ${DIRS}
${SNAPSHOT_DIR}:
mkdir ${SNAPSHOT_DIR}
_dist: clean ${DIRS}
${DIRS}: ${RELEASE_DIR}
svn export -r $(REPO_VERSION) $(REPO_URL)/$@ $(RELEASE_DIR)/$@ ; \
.PHONY: export_dir
export_dir:
mkdir $(__EXPORT_DIR)
/usr/bin/bzr export --per-file-timestamps -r $(REPO_VERSION) $(__EXPORT_DIR) $(REPO_URL)
echo "$(REPO_URL) $(REPO_VERSION)" > $(__EXPORT_DIR)/.stamp_rev
clean:
-rm -rf ${RELEASE_DIR}
-rm -rf ./${RELEASE_DIR} ./apparmor-${VERSION}~*
setup:
cd $(__SETUP_DIR)/libraries/libapparmor && ./autogen.sh
.PHONY: tag
tag:
bzr tag apparmor_${VERSION}

View File

@@ -1,96 +1,126 @@
# $Id$
# This publication is intellectual property of Novell Inc. Its contents
# can be duplicated, either in part or in whole, provided that a copyright
# label is visibly located on each copy.
# This publication is intellectual property of Novell Inc. and Canonical
# Ltd. Its contents can be duplicated, either in part or in whole, provided
# that a copyright label is visibly located on each copy.
#
# All information found in this book has been compiled with utmost
# attention to detail. However, this does not guarantee complete accuracy.
# Neither SUSE LINUX GmbH, the authors, nor the translators shall be held
# liable for possible errors or the consequences thereof.
# Neither SUSE LINUX GmbH, Canonical Ltd, the authors, nor the translators
# shall be held liable for possible errors or the consequences thereof.
#
# Many of the software and hardware descriptions cited in this book
# are registered trademarks. All trade names are subject to copyright
# restrictions and may be registered trade marks. SUSE LINUX GmbH
# essentially adheres to the manufacturer's spelling.
# and Canonical Ltd. essentially adhere to the manufacturer's spelling.
#
# Names of products and trademarks appearing in this book (with or without
# specific notation) are likewise subject to trademark and trade protection
# laws and may thus fall under copyright restrictions.
#
# Please direct suggestions and comments to apparmor-general@forge.novell.com.
=pod
=head1 NAME
mod_apparmor - fine-grained AppArmor confinement for apache
mod_apparmor - fine-grained AppArmor confinement for Apache
=head1 DESCRIPTION
An AppArmor profile applies to an executable program; if a portion of
the program needs different access permissions than other portions,
the program can "change hats" via change_hat(2) to a different role,
also known as a subprofile. The mod_apparmor apache module uses the
change_hat(2) mechanism to offer more fine-grained confinement of dynamic
elements within apache such as individual php and perl scripts, while
the program can "change hats" via aa_change_hat(2) to a different role,
also known as a subprofile. The mod_apparmor Apache module uses the
aa_change_hat(2) mechanism to offer more fine-grained confinement of dynamic
elements within Apache such as individual php and perl scripts, while
still allowing the performance benefits of using mod_php and mod_perl.
To use mod_apparmor with apache, ensure that mod_apparmor is configured to
be loaded into apache, either via yast or manual editing of the httpd(8)
configuration files, and restart apache. Make sure that apparmor is also
functioning.
To use mod_apparmor with Apache, ensure that mod_apparmor is configured to
be loaded into Apache, either via a2enmod, yast or manual editing of the
apache2(8)/httpd(8) configuration files, and restart Apache. Make sure that
apparmor is also functioning.
Once mod_apparmor is loaded within apache, all requests to apache will
Once mod_apparmor is loaded within Apache, all requests to Apache will
cause mod_apparmor to attempt to change into a hat named by the URI
(e.g. /app/some.cgi). If no such hat is found, it will fall back to
attempting to use the hat DEFAULT_URI; if that also does not exist,
it will fall back to using the global apache profile. Most static web
it will fall back to using the global Apache profile. Most static web
pages can simply make use of the DEFAULT_URI hat.
However, defining hats for every URI/URL would become tedious, so there
are a couple of configuration options that mod_apparmor supports:
Additionally, before any requests come in to Apache, mod_apparmor
will attempt to change hat into the HANDLING_UNTRUSTED_INPUT hat.
mod_apparmor will attempt to use this hat while Apache is doing the
initial parsing of a given http request, before its given to a specific
handler (like mod_php) for processing.
Because defining hats for every URI/URL often becomes tedious, mod_apparmor
provides the AAHatName and AADefaultHatName Apache configuration options.
=over 4
=item B<AAHatName>
AAHatName allows you to specify a hat to be used for a given apache
directory or location directive (see the apache documenation for more
AAHatName allows you to specify a hat to be used for a given Apache
E<lt>DirectoryE<gt>, E<lt>DirectoryMatch>, E<lt>LocationE<gt> or
E<lt>LocationMatchE<gt> directive (see the Apache documenation for more
details). Note that mod_apparmor behavior can become confused if
directory and location directives are intermingled; it's preferred to
stick to one type of directive. If the hat specified by AAHatName does
not exist in the apache profile, then it falls back to the behavior
above.
E<lt>Directory*E<gt> and E<lt>Location*E<gt> directives are intermingled
and it is recommended to use one type of directive. If the hat specified by
AAHatName does not exist in the Apache profile, then it falls back to the
behavior described above.
=item B<AADefaultHatName>
AADefaultHatName allows you to specify a default hat to be used for
vhosts and other apache server directives, so that you can have
different defaults for different virtual hosts. This can be overridden
by an AAHatName directive. If the AADefaultHatName hat does not exist,
it falls back to the behavior described above.
virtual hosts and other Apache server directives, so that you can have
different defaults for different virtual hosts. This can be overridden by
the AAHatName directive and is checked for only if there isn't a matching
AAHatName or hat named by the URI. If the AADefaultHatName hat does not
exist, it falls back to the DEFAULT_URI hat if it exists (as described
above).
=back
Additionally, before any requests come in to apache, mod_apparmor
will attempt to change hat into the HANDLING_UNTRUSTED_INPUT hat.
mod_apparmor will attempt to use this hat while apache is doing the
initial parsing of a given http request, before its given to a specific
handler (like mod_php) for processing.
=head1 URI REQUEST SUMMARY
When profiling with mod_apparmor, it is helpful to keep the following order
of operations in mind:
On each URI request, mod_apparmor will first aa_change_hat(2) into
^HANDLING_UNTRUSTED_INPUT, if it exists.
Then, after performing the initial parsing of the request, mod_apparmor
will:
=over 2
1. try to aa_change_hat(2) into a matching AAHatName hat if it exists and
applies, otherwise it will
2. try to aa_change_hat(2) into the URI itself, otherwise it will
3. try to aa_change_hat(2) into an AADefaultHatName hat if it has been defined
for the server/vhost, otherwise it will
4. try to aa_change_hat(2) into the DEFAULT_URI hat, if it exists, otherwise it
will
5. fall back to the global Apache policy
=back
=head1 BUGS
mod_apparmor() currently only supports apache2, and has only been tested
with the prefork MPM configuration -- threaded configurations of apache
with the prefork MPM configuration -- threaded configurations of Apache
may not work correctly.
There are likely other bugs lurking about; if you find any, please report
them to bugzilla at L<http://bugzilla.novell.com>.
them at L<http://https://bugs.launchpad.net/apparmor/+filebug>.
=head1 SEE ALSO
apparmor(7), subdomain.conf(5), apparmor_parser(8), and
L<http://forge.novell.com/modules/xfmod/project/?apparmor>.
apparmor(7), subdomain.conf(5), apparmor_parser(8), aa_change_hat(2) and
L<http://wiki.apparmor.net>.
=cut

View File

@@ -1,10 +1,14 @@
/* pam_apparmor module */
/*
* $Id$
* Copyright (c) 2006
* NOVELL (All rights reserved)
*
* Copyright (c) 2010
* Canonical, Ltd.(All rights reserved)
*
* Written by Jesse Michael <jmichael@suse.de> 2006/08/24
* and Steve Beattie <sbeattie@suse.de> 2006/10/25
* and Steve Beattie <sbeattie@ubuntu.com> 2006/10/25
*
* Based off of pam_motd by:
* Ben Collins <bcollins@debian.org> 2005/10/04
@@ -167,6 +171,7 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags,
break;
case EPERM: /* Disable when ECHILD patch gets accepted */
case EACCES:
case ENOENT:
/* failed to change into attempted hat, so we'll
* jump back out and try the next one */
break;

View File

@@ -25,7 +25,7 @@
# directories
DISTRIBUTION=AppArmor
VERSION=2.5
VERSION=2.5.2~rc1
# OVERRIDABLE variables
# Set these variables before including Make.rules to change its behavior
@@ -48,15 +48,15 @@ BUILDDIR=$(shell if [ -d "${TESTBUILDDIR}" ] ; then \
echo "/tmp/${NAME}" ; \
fi ;)
endif
RPMHOSTVENDOR=$(shell rpm --eval "%{_host_vendor}")
RPMHOSTVENDOR=$(shell which rpm > /dev/null && rpm --eval "%{_host_vendor}")
ifndef DISTRO
DISTRO=$(shell if [ -f /etc/slackware-version ] ; then \
echo slackware ; \
elif [ -f /etc/debian_version ] ; then \
echo debian ;\
elif [ ${RPMHOSTVENDOR} = "suse" ] ; then \
elif [ "${RPMHOSTVENDOR}" = "suse" ] ; then \
echo suse ;\
elif [ ${RPMHOSTVENDOR} = "redhat" ] ; then \
elif [ "${RPMHOSTVENDOR}" = "redhat" ] ; then \
echo rhel4 ;\
else \
echo unknown ;\
@@ -75,15 +75,16 @@ RPMARG=--define "_topdir $(BUILDDIR:/=)" \
# /usr/bin/svn info . 2> /dev/null | grep "^Last Changed Rev:" | sed "s/^Last Changed Rev: //" ; \
# fi ; \
# fi)
REPO_VERSION=$(shell if [ -x /usr/bin/svn ] ; then \
/usr/bin/svn info . 2> /dev/null | grep "^Last Changed Rev:" | sed "s/^Last Changed Rev: //" ; \
REPO_VERSION=$(shell if [ -x /usr/bin/bzr ] ; then \
(/usr/bin/bzr version-info . 2> /dev/null || echo revno: 1) | awk '/^revno:/ { print $$2 }' ; \
else echo 1; \
fi)
REPO_URL=$(shell if [ -x /usr/bin/svn ] ; then \
/usr/bin/svn info . 2> /dev/null | grep "^URL:" | sed "s/^URL: //" ; \
fi)
COMMON_REPO_URL=$(shell if [ -x /usr/bin/svn ] ; then \
/usr/bin/svn info $(COMMONDIR) 2> /dev/null | grep "^URL:" | sed "s/^URL: //" ; \
fi)
#REPO_URL=$(shell if [ -x /usr/bin/svn ] ; then \
# /usr/bin/svn info . 2> /dev/null | grep "^URL:" | sed "s/^URL: //" ; \
# fi)
#COMMON_REPO_URL=$(shell if [ -x /usr/bin/svn ] ; then \
# /usr/bin/svn info $(COMMONDIR) 2> /dev/null | grep "^URL:" | sed "s/^URL: //" ; \
# fi)
ifdef EXTERNAL_PACKAGE
RPMARG+=--define "_sourcedir $(shell pwd)"
@@ -161,6 +162,11 @@ endif
version:
rpm -q --define "_sourcedir ." ${RPMARG} --specfile ${SPECFILE}
.PHONY: repo_version
.SILENT: repo_version
repo_version:
echo $(REPO_VERSION)
.PHONY: build_dir
build_dir: $(BUILDRPMSUBDIRS)

View File

@@ -11,6 +11,7 @@
#include <stdlib.h>
#include <string.h>
#include <glib/gi18n.h>
#include <libgnome/gnome-program.h>
#include "preferences_dialog.h"
#include "reject_list.h"
#include "apparmor-applet.h"

View File

@@ -1,144 +0,0 @@
From: John Johansen <jjohansen@suse.de>
Subject: Fix __d_path to allow for old and new behavior bnc#380763
Fix __d_path so that it can be told whether or not to connect
disconnect path to the root. This is easier and more efficient
than trying to reconnect these paths for d_path and get_cwd
after the fact.
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/dcache.c | 57 ++++++++++++++++++-------------------------------
fs/namespace.c | 2 -
include/linux/dcache.h | 2 -
3 files changed, 24 insertions(+), 37 deletions(-)
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1772,6 +1772,7 @@ shouldnt_be_hashed:
* @buffer: buffer to return value in
* @buflen: buffer length
* @fail_deleted: what to return for deleted files
+ * @disconnect: don't return a path starting with / when disconnected
*
* 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,
@@ -1784,9 +1785,10 @@ shouldnt_be_hashed:
*/
char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
struct dentry *root, struct vfsmount *rootmnt,
- char *buffer, int buflen, int fail_deleted)
+ char *buffer, int buflen, int fail_deleted, int disconnect)
{
- int namelen, is_slash, vfsmount_locked = 0;
+ int namelen, vfsmount_locked = 0;
+ const unsigned char *name;
if (buflen < 2)
return ERR_PTR(-ENAMETOOLONG);
@@ -1847,27 +1849,26 @@ global_root:
* unconnected dentry, or the file is on a pseudo filesystem.
*/
namelen = dentry->d_name.len;
- is_slash = (namelen == 1 && *dentry->d_name.name == '/');
- if (is_slash || (dentry->d_sb->s_flags & MS_NOUSER)) {
- /*
- * Make sure we won't return a pathname starting with '/'.
- *
- * Historically, we also glue together the root dentry and
- * remaining name for pseudo filesystems like pipefs, which
- * have the MS_NOUSER flag set. This results in pathnames
- * like "pipe:[439336]".
- */
- if (*buffer == '/') {
- buffer++;
- buflen++;
- }
- if (is_slash)
- goto out;
+ name = dentry->d_name.name;
+
+ /*
+ * If this is a root dentry, then overwrite the slash. This
+ * will also DTRT with pseudo filesystems which have root
+ * dentries named "foo:".
+ */
+ if (IS_ROOT(dentry)) {
+ buffer++;
+ buflen++;
+ }
+ if (disconnect && *name == '/') {
+ /* Make sure we won't return a pathname starting with '/' */
+ name++;
+ namelen--;
}
if (buflen < namelen)
goto Elong;
buffer -= namelen;
- memcpy(buffer, dentry->d_name.name, namelen);
+ memcpy(buffer, name, namelen);
goto out;
Elong:
@@ -1875,18 +1876,6 @@ Elong:
goto out;
}
-static char *__connect_d_path(char *path, char *buffer)
-{
- if (!IS_ERR(path) && *path != '/') {
- /* Pretend that disconnected paths are hanging off the root. */
- if (path == buffer)
- path = ERR_PTR(-ENAMETOOLONG);
- else
- *--path = '/';
- }
- return path;
-}
-
/* write full pathname into buffer and return start of pathname */
char *d_path(struct dentry *dentry, struct vfsmount *vfsmnt, char *buf,
int buflen)
@@ -1909,8 +1898,7 @@ char *d_path(struct dentry *dentry, stru
rootmnt = mntget(current->fs->rootmnt);
root = dget(current->fs->root);
read_unlock(&current->fs->lock);
- res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen, 0);
- res = __connect_d_path(res, buf);
+ res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen, 0, 0);
dput(root);
mntput(rootmnt);
return res;
@@ -1972,8 +1960,7 @@ asmlinkage long sys_getcwd(char __user *
root = dget(current->fs->root);
read_unlock(&current->fs->lock);
- cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE, 1);
- cwd = __connect_d_path(cwd, page);
+ cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE, 1, 0);
error = PTR_ERR(cwd);
if (IS_ERR(cwd))
goto out;
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1901,7 +1901,7 @@ char *d_namespace_path(struct dentry *de
mntput(rootmnt);
if (nsrootmnt)
root = dget(nsrootmnt->mnt_root);
- res = __d_path(dentry, vfsmnt, root, nsrootmnt, buf, buflen, 1);
+ res = __d_path(dentry, vfsmnt, root, nsrootmnt, buf, buflen, 1, 1);
dput(root);
mntput(nsrootmnt);
/* Prevent empty path for lazily unmounted filesystems. */
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -301,7 +301,7 @@ extern int d_validate(struct dentry *, s
extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
extern char *__d_path(struct dentry *, struct vfsmount *, struct dentry *,
- struct vfsmount *, char *, int, int);
+ struct vfsmount *, char *, int, int, int);
extern char * d_path(struct dentry *, struct vfsmount *, char *, int);
/* Allocation counts.. */

View File

@@ -1,72 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: 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 <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
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)
@@ -116,6 +116,13 @@
#define AUDIT_MAC_IPSEC_DELSPD 1414 /* Not used */
#define AUDIT_MAC_IPSEC_EVENT 1415 /* Audit an IPSec event */
+#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_HINT 1504 /* 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_MSG 1799
#define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */
@@ -513,6 +520,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 void audit_log_vformat(struct audit_buffer *ab,
+ const char *fmt, va_list args)
+ __attribute__((format(printf,2,0)));
extern void audit_log_format(struct audit_buffer *ab,
const char *fmt, ...)
__attribute__((format(printf,2,3)));
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1215,8 +1215,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;
@@ -1471,3 +1470,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);

View File

@@ -1,30 +0,0 @@
From: John Johansen <jjohansen@suse.de>
Subject: Add AppArmor LSM to security/Makefile
Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
security/Kconfig | 1 +
security/Makefile | 1 +
2 files changed, 2 insertions(+)
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -104,6 +104,7 @@ config SECURITY_ROOTPLUG
If you are unsure how to answer this question, answer N.
source security/selinux/Kconfig
+source security/apparmor/Kconfig
endmenu
--- a/security/Makefile
+++ b/security/Makefile
@@ -14,5 +14,6 @@ endif
obj-$(CONFIG_SECURITY) += security.o dummy.o inode.o
# Must precede capability.o in order to stack properly.
obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
+obj-$(CONFIG_SECURITY_APPARMOR) += commoncap.o apparmor/
obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o
obj-$(CONFIG_SECURITY_ROOTPLUG) += commoncap.o root_plug.o

View File

@@ -1,904 +0,0 @@
From: John Johansen <jjohansen@suse.de>
Subject: AppArmor: Module and LSM hooks
Module parameters, LSM hooks, initialization and teardown.
Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
security/apparmor/lsm.c | 889 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 889 insertions(+)
--- /dev/null
+++ b/security/apparmor/lsm.c
@@ -0,0 +1,889 @@
+/*
+ * 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"
+
+/* Flag indicating whether initialization completed */
+int apparmor_initialized = 0;
+
+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");
+
+/* Boot time disable flag */
+#ifdef CONFIG_SECURITY_APPARMOR_DISABLE
+#define AA_ENABLED_PERMS 0600
+#else
+#define AA_ENABLED_PERMS 0400
+#endif
+static int param_set_aa_enabled(const char *val, struct kernel_param *kp);
+unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
+module_param_call(enabled, param_set_aa_enabled, param_get_aauint,
+ &apparmor_enabled, AA_ENABLED_PERMS);
+MODULE_PARM_DESC(apparmor_enabled, "Enable/Disable Apparmor on boot");
+
+static int __init apparmor_enabled_setup(char *str)
+{
+ apparmor_enabled = simple_strtol(str, NULL, 0);
+ return 1;
+}
+__setup("apparmor=", apparmor_enabled_setup);
+
+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);
+}
+
+/* allow run time disabling of apparmor */
+static int param_set_aa_enabled(const char *val, struct kernel_param *kp)
+{
+ char *endp;
+ unsigned long l;
+
+ if (!apparmor_initialized) {
+ apparmor_enabled = 0;
+ return 0;
+ }
+
+ if (aa_task_context(current))
+ return -EPERM;
+
+ if (!apparmor_enabled)
+ return -EINVAL;
+
+ if (!val)
+ return -EINVAL;
+
+ l = simple_strtoul(val, &endp, 0);
+ if (endp == val || l != 0)
+ return -EINVAL;
+
+ apparmor_enabled = 0;
+ apparmor_disable();
+ return 0;
+}
+
+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;
+ } else {
+ struct aa_task_context *child_cxt =
+ aa_task_context(child);
+
+ error = aa_may_ptrace(cxt, child_cxt ?
+ child_cxt->profile : NULL);
+ if (PROFILE_COMPLAIN(cxt->profile)) {
+ 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;
+ aa_audit_hint(cxt->profile, &sa);
+ }
+ }
+ }
+ rcu_read_unlock();
+
+ return error;
+}
+
+static int apparmor_capable(struct task_struct *task, int cap)
+{
+ int error;
+ struct aa_task_context *cxt;
+
+ /* cap_capable returns 0 on success, else -EPERM */
+ error = cap_capable(task, cap);
+
+ rcu_read_lock();
+ cxt = aa_task_context(task);
+ if (cxt && (!error || cap_raised(cxt->profile->set_caps, cap)))
+ error = aa_capability(cxt, cap);
+ rcu_read_unlock();
+
+ return error;
+}
+
+static int apparmor_sysctl(struct ctl_table *table, int op)
+{
+ struct aa_profile *profile = aa_get_profile(current);
+ int error = 0;
+
+ if (profile) {
+ char *buffer, *name;
+ int mask;
+
+ mask = 0;
+ if (op & 4)
+ mask |= MAY_READ;
+ if (op & 2)
+ mask |= MAY_WRITE;
+
+ error = -ENOMEM;
+ buffer = (char*)__get_free_page(GFP_KERNEL);
+ if (!buffer)
+ goto out;
+ name = sysctl_pathname(table, buffer, PAGE_SIZE);
+ if (name && name - buffer >= 5) {
+ name -= 5;
+ memcpy(name, "/proc", 5);
+ error = aa_perm_path(profile, "sysctl", name, mask, 0);
+ }
+ free_page((unsigned long)buffer);
+ }
+
+out:
+ aa_put_profile(profile);
+ return error;
+}
+
+static int apparmor_bprm_set_security(struct linux_binprm *bprm)
+{
+ /* handle capability bits with setuid, etc */
+ cap_bprm_set_security(bprm);
+ /* already set based on script name */
+ if (bprm->sh_bang)
+ return 0;
+ return aa_register(bprm);
+}
+
+static int apparmor_bprm_secureexec(struct linux_binprm *bprm)
+{
+ int ret = cap_bprm_secureexec(bprm);
+
+ if (!ret && (unsigned long)bprm->security & AA_SECURE_EXEC_NEEDED) {
+ AA_DEBUG("%s: secureexec required for %s\n",
+ __FUNCTION__, bprm->filename);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+static int apparmor_sb_mount(char *dev_name, struct nameidata *nd, char *type,
+ unsigned long flags, void *data)
+{
+ return aa_reject_syscall(current, GFP_KERNEL, "mount");
+}
+
+static int apparmor_umount(struct vfsmount *mnt, int flags)
+{
+ return aa_reject_syscall(current, GFP_KERNEL, "umount");
+}
+
+static int apparmor_inode_mkdir(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt, int mask)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ if (!mnt || !mediated_filesystem(dir))
+ goto out;
+
+ profile = aa_get_profile(current);
+
+ if (profile)
+ error = aa_perm_dir(profile, "inode_mkdir", dentry, mnt,
+ MAY_WRITE);
+
+ aa_put_profile(profile);
+
+out:
+ return error;
+}
+
+static int apparmor_inode_rmdir(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ if (!mnt || !mediated_filesystem(dir))
+ goto out;
+
+ profile = aa_get_profile(current);
+
+ if (profile)
+ error = aa_perm_dir(profile, "inode_rmdir", dentry, mnt,
+ MAY_WRITE);
+
+ aa_put_profile(profile);
+
+out:
+ return error;
+}
+
+static int aa_permission(const char *operation, struct inode *inode,
+ struct dentry *dentry, struct vfsmount *mnt,
+ int mask, int check)
+{
+ int error = 0;
+
+ if (mnt && mediated_filesystem(inode)) {
+ struct aa_profile *profile;
+
+ profile = aa_get_profile(current);
+ if (profile)
+ error = aa_perm(profile, operation, dentry, mnt, mask,
+ check);
+ aa_put_profile(profile);
+ }
+ return error;
+}
+
+static inline int aa_mask_permissions(int mask)
+{
+ if (mask & MAY_APPEND)
+ mask &= (MAY_READ | MAY_APPEND | MAY_EXEC);
+ else
+ mask &= (MAY_READ | MAY_WRITE | MAY_EXEC);
+ return mask;
+}
+
+static int apparmor_inode_create(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt, int mask)
+{
+ return aa_permission("inode_create", dir, dentry, mnt, MAY_APPEND, 0);
+}
+
+static int apparmor_inode_link(struct dentry *old_dentry,
+ struct vfsmount *old_mnt, struct inode *dir,
+ struct dentry *new_dentry,
+ struct vfsmount *new_mnt)
+{
+ int error = 0;
+ struct aa_profile *profile;
+
+ if (!old_mnt || !new_mnt || !mediated_filesystem(dir))
+ goto out;
+
+ profile = aa_get_profile(current);
+
+ if (profile)
+ error = aa_link(profile, new_dentry, new_mnt,
+ old_dentry, old_mnt);
+
+ aa_put_profile(profile);
+
+out:
+ return error;
+}
+
+static int apparmor_inode_unlink(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt)
+{
+ int check = 0;
+
+ if (S_ISDIR(dentry->d_inode->i_mode))
+ check |= AA_CHECK_DIR;
+ return aa_permission("inode_unlink", dir, dentry, mnt, MAY_WRITE,
+ check);
+}
+
+static int apparmor_inode_symlink(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt, const char *old_name)
+{
+ return aa_permission("inode_symlink", dir, dentry, mnt, MAY_WRITE, 0);
+}
+
+static int apparmor_inode_mknod(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt, int mode, dev_t dev)
+{
+ return aa_permission("inode_mknod", dir, dentry, mnt, MAY_WRITE, 0);
+}
+
+static int apparmor_inode_rename(struct inode *old_dir,
+ struct dentry *old_dentry,
+ struct vfsmount *old_mnt,
+ struct inode *new_dir,
+ struct dentry *new_dentry,
+ struct vfsmount *new_mnt)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ if ((!old_mnt && !new_mnt) || !mediated_filesystem(old_dir))
+ goto out;
+
+ profile = aa_get_profile(current);
+
+ if (profile) {
+ struct inode *inode = old_dentry->d_inode;
+ int check = 0;
+
+ if (inode && S_ISDIR(inode->i_mode))
+ check |= AA_CHECK_DIR;
+ if (old_mnt)
+ error = aa_perm(profile, "inode_rename", old_dentry,
+ old_mnt, MAY_READ | MAY_WRITE, check);
+
+ if (!error && new_mnt) {
+ error = aa_perm(profile, "inode_rename", new_dentry,
+ new_mnt, MAY_WRITE, check);
+ }
+ }
+
+ aa_put_profile(profile);
+
+out:
+ return error;
+}
+
+static int apparmor_inode_permission(struct inode *inode, int mask,
+ struct nameidata *nd)
+{
+ int check = 0;
+
+ if (!nd || nd->flags & (LOOKUP_PARENT | LOOKUP_CONTINUE))
+ return 0;
+ mask = aa_mask_permissions(mask);
+ if (S_ISDIR(inode->i_mode)) {
+ check |= AA_CHECK_DIR;
+ /* allow traverse accesses to directories */
+ mask &= ~MAY_EXEC;
+ }
+ return aa_permission("inode_permission", inode, nd->dentry, nd->mnt,
+ mask, check);
+}
+
+static int apparmor_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
+ struct iattr *iattr)
+{
+ int error = 0;
+
+ if (!mnt)
+ goto out;
+
+ if (mediated_filesystem(dentry->d_inode)) {
+ struct aa_profile *profile;
+
+ profile = aa_get_profile(current);
+ /*
+ * Mediate any attempt to change attributes of a file
+ * (chmod, chown, chgrp, etc)
+ */
+ if (profile)
+ error = aa_attr(profile, dentry, mnt, iattr);
+
+ aa_put_profile(profile);
+ }
+
+out:
+ return error;
+}
+
+static int aa_xattr_permission(struct dentry *dentry, struct vfsmount *mnt,
+ const char *operation, int mask,
+ struct file *file)
+{
+ int error = 0;
+
+ if (mnt && mediated_filesystem(dentry->d_inode)) {
+ struct aa_profile *profile = aa_get_profile(current);
+ int check = file ? AA_CHECK_FD : 0;
+
+ if (profile)
+ error = aa_perm_xattr(profile, operation, dentry, mnt,
+ mask, check);
+ aa_put_profile(profile);
+ }
+
+ return error;
+}
+
+static int apparmor_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size,
+ int flags, struct file *file)
+{
+ return aa_xattr_permission(dentry, mnt, "xattr set", MAY_WRITE, file);
+}
+
+static int apparmor_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, struct file *file)
+{
+ return aa_xattr_permission(dentry, mnt, "xattr get", MAY_READ, file);
+}
+
+static int apparmor_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
+ struct file *file)
+{
+ return aa_xattr_permission(dentry, mnt, "xattr list", MAY_READ, file);
+}
+
+static int apparmor_inode_removexattr(struct dentry *dentry,
+ struct vfsmount *mnt, char *name,
+ struct file *file)
+{
+ return aa_xattr_permission(dentry, mnt, "xattr remove", MAY_WRITE,
+ file);
+}
+
+static int aa_file_permission(const char *op, struct file *file, int mask)
+{
+ struct aa_profile *profile;
+ struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
+ int error = 0;
+
+ if (!file_profile)
+ goto out;
+
+ /*
+ * If this file was opened under a different profile, we
+ * revalidate the access against the current profile.
+ */
+ profile = aa_get_profile(current);
+ if (profile && (file_profile != profile || mask & AA_MAY_LOCK)) {
+ struct dentry *dentry = file->f_dentry;
+ struct vfsmount *mnt = file->f_vfsmnt;
+ struct inode *inode = dentry->d_inode;
+ int check = AA_CHECK_FD;
+
+ /*
+ * FIXME: We should remember which profiles we revalidated
+ * against.
+ */
+ if (S_ISDIR(inode->i_mode))
+ check |= AA_CHECK_DIR;
+ error = aa_permission(op, inode, dentry, mnt, mask, check);
+ }
+ aa_put_profile(profile);
+
+out:
+ return error;
+}
+
+static int apparmor_file_permission(struct file *file, int mask)
+{
+ return aa_file_permission("file_permission", file,
+ aa_mask_permissions(mask));
+}
+
+static inline int apparmor_file_lock (struct file *file, unsigned int cmd)
+{
+ int mask = AA_MAY_LOCK;
+ if (cmd == F_WRLCK)
+ mask |= MAY_WRITE;
+ return aa_file_permission("file_lock", file, mask);
+}
+
+static int apparmor_file_alloc_security(struct file *file)
+{
+ struct aa_profile *profile;
+
+ profile = aa_get_profile(current);
+ if (profile)
+ file->f_security = profile;
+
+ return 0;
+}
+
+static void apparmor_file_free_security(struct file *file)
+{
+ struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
+
+ aa_put_profile(file_profile);
+}
+
+static inline int aa_mmap(struct file *file, const char *operation,
+ unsigned long prot, unsigned long flags)
+{
+ struct dentry *dentry;
+ int mask = 0;
+
+ if (!file || !file->f_security)
+ return 0;
+
+ if (prot & PROT_READ)
+ mask |= MAY_READ;
+ /* Private mappings don't require write perms since they don't
+ * write back to the files */
+ if ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE))
+ mask |= MAY_WRITE;
+ if (prot & PROT_EXEC)
+ mask |= AA_EXEC_MMAP;
+
+ dentry = file->f_dentry;
+ return aa_permission(operation, dentry->d_inode, dentry,
+ file->f_vfsmnt, mask, AA_CHECK_FD);
+}
+
+static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
+ unsigned long prot, unsigned long flags,
+ unsigned long addr, unsigned long addr_only)
+{
+ if ((addr < mmap_min_addr) && !capable(CAP_SYS_RAWIO)) {
+ struct aa_profile *profile = aa_get_profile(current);
+ if (profile)
+ /* future control check here */
+ return -EACCES;
+ else
+ return -EACCES;
+ aa_put_profile(profile);
+ }
+
+ return aa_mmap(file, "file_mmap", prot, flags);
+}
+
+static int apparmor_file_mprotect(struct vm_area_struct *vma,
+ unsigned long reqprot, unsigned long prot)
+{
+ return aa_mmap(vma->vm_file, "file_mprotect", prot,
+ !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
+}
+
+static int apparmor_task_alloc_security(struct task_struct *task)
+{
+ return aa_clone(task);
+}
+
+/*
+ * Called from IRQ context from RCU callback.
+ */
+static void apparmor_task_free_security(struct task_struct *task)
+{
+ aa_release(task);
+}
+
+static int apparmor_getprocattr(struct task_struct *task, char *name,
+ char **value)
+{
+ unsigned len;
+ int error;
+ struct aa_profile *profile;
+
+ /* AppArmor only supports the "current" process attribute */
+ if (strcmp(name, "current") != 0)
+ return -EINVAL;
+
+ /* must be task querying itself or admin */
+ if (current != task && !capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ profile = aa_get_profile(task);
+ error = aa_getprocattr(profile, value, &len);
+ aa_put_profile(profile);
+ if (!error)
+ error = len;
+
+ return error;
+}
+
+static int apparmor_setprocattr(struct task_struct *task, char *name,
+ void *value, size_t size)
+{
+ char *command, *args;
+ int error;
+
+ if (strcmp(name, "current") != 0 || size == 0 || size >= PAGE_SIZE)
+ return -EINVAL;
+ args = value;
+ args[size] = '\0';
+ args = strstrip(args);
+ command = strsep(&args, " ");
+ if (!args)
+ return -EINVAL;
+ while (isspace(*args))
+ args++;
+ if (!*args)
+ return -EINVAL;
+
+ if (strcmp(command, "changehat") == 0) {
+ if (current != task)
+ return -EACCES;
+ error = aa_setprocattr_changehat(args);
+ } else if (strcmp(command, "changeprofile") == 0) {
+ if (current != task)
+ return -EACCES;
+ error = aa_setprocattr_changeprofile(args);
+ } else if (strcmp(command, "setprofile") == 0) {
+ struct aa_profile *profile;
+
+ /* Only an unconfined process with admin capabilities
+ * may change the profile of another task.
+ */
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+
+ profile = aa_get_profile(current);
+ if (profile) {
+ struct aa_audit sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.operation = "profile_set";
+ sa.gfp_mask = GFP_KERNEL;
+ sa.task = task->pid;
+ sa.info = "from confined process";
+ aa_audit_reject(profile, &sa);
+ aa_put_profile(profile);
+ return -EACCES;
+ }
+ error = aa_setprocattr_setprofile(task, args);
+ } else {
+ struct aa_audit sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.operation = "setprocattr";
+ sa.gfp_mask = GFP_KERNEL;
+ sa.info = "invalid command";
+ sa.name = command;
+ sa.task = task->pid;
+ aa_audit_reject(NULL, &sa);
+ return -EINVAL;
+ }
+
+ if (!error)
+ error = size;
+ return error;
+}
+
+struct security_operations apparmor_ops = {
+ .ptrace = apparmor_ptrace,
+ .capget = cap_capget,
+ .capset_check = cap_capset_check,
+ .capset_set = cap_capset_set,
+ .sysctl = apparmor_sysctl,
+ .capable = apparmor_capable,
+ .syslog = cap_syslog,
+
+ .netlink_send = cap_netlink_send,
+ .netlink_recv = cap_netlink_recv,
+
+ .bprm_apply_creds = cap_bprm_apply_creds,
+ .bprm_set_security = apparmor_bprm_set_security,
+ .bprm_secureexec = apparmor_bprm_secureexec,
+
+ .sb_mount = apparmor_sb_mount,
+ .sb_umount = apparmor_umount,
+
+ .inode_mkdir = apparmor_inode_mkdir,
+ .inode_rmdir = apparmor_inode_rmdir,
+ .inode_create = apparmor_inode_create,
+ .inode_link = apparmor_inode_link,
+ .inode_unlink = apparmor_inode_unlink,
+ .inode_symlink = apparmor_inode_symlink,
+ .inode_mknod = apparmor_inode_mknod,
+ .inode_rename = apparmor_inode_rename,
+ .inode_permission = apparmor_inode_permission,
+ .inode_setattr = apparmor_inode_setattr,
+ .inode_setxattr = apparmor_inode_setxattr,
+ .inode_getxattr = apparmor_inode_getxattr,
+ .inode_listxattr = apparmor_inode_listxattr,
+ .inode_removexattr = apparmor_inode_removexattr,
+ .file_permission = apparmor_file_permission,
+ .file_alloc_security = apparmor_file_alloc_security,
+ .file_free_security = apparmor_file_free_security,
+ .file_mmap = apparmor_file_mmap,
+ .file_mprotect = apparmor_file_mprotect,
+ .file_lock = apparmor_file_lock,
+
+ .task_alloc_security = apparmor_task_alloc_security,
+ .task_free_security = apparmor_task_free_security,
+ .task_post_setuid = cap_task_post_setuid,
+ .task_reparent_to_init = cap_task_reparent_to_init,
+
+ .getprocattr = apparmor_getprocattr,
+ .setprocattr = apparmor_setprocattr,
+};
+
+void info_message(const char *str)
+{
+ struct aa_audit sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.gfp_mask = GFP_KERNEL;
+ sa.info = str;
+ printk(KERN_INFO "AppArmor: %s\n", str);
+ if (audit_enabled)
+ aa_audit_message(NULL, &sa, AUDIT_APPARMOR_STATUS);
+}
+
+static int __init apparmor_init(void)
+{
+ int error;
+
+ if (!apparmor_enabled) {
+ info_message("AppArmor disabled by boottime parameter\n");
+ return 0;
+ }
+
+ if ((error = create_apparmorfs())) {
+ AA_ERROR("Unable to activate AppArmor filesystem\n");
+ goto createfs_out;
+ }
+
+ if ((error = alloc_default_namespace())){
+ AA_ERROR("Unable to allocate default profile namespace\n");
+ goto alloc_out;
+ }
+
+ if ((error = register_security(&apparmor_ops))) {
+ AA_ERROR("Unable to register AppArmor\n");
+ goto register_security_out;
+ }
+
+ /* Report that AppArmor successfully initialized */
+ apparmor_initialized = 1;
+ if (apparmor_complain)
+ info_message("AppArmor initialized: complainmode enabled");
+ else
+ info_message("AppArmor initialized");
+
+ return error;
+
+register_security_out:
+ free_default_namespace();
+
+alloc_out:
+ destroy_apparmorfs();
+
+createfs_out:
+ return error;
+
+}
+
+security_initcall(apparmor_init);
+
+void apparmor_disable(void)
+{
+ /* Remove and release all the profiles on the profile list. */
+ mutex_lock(&aa_interface_lock);
+ aa_profile_ns_list_release();
+
+ /* FIXME: cleanup profiles references on files */
+ free_default_namespace();
+
+ /*
+ * Delay for an rcu cycle to make sure that all active task
+ * context readers have finished, and all profiles have been
+ * freed by their rcu callbacks.
+ */
+ synchronize_rcu();
+
+ destroy_apparmorfs();
+ mutex_unlock(&aa_interface_lock);
+
+ apparmor_initialized = 0;
+
+ info_message("AppArmor protection removed");
+}
+
+MODULE_DESCRIPTION("AppArmor process confinement");
+MODULE_AUTHOR("Novell/Immunix, http://bugs.opensuse.org");
+MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,408 +0,0 @@
From: John Johansen <jjohansen@suse.de>
Subject: AppArmor: Simplified network controls for AppArmor
Simple network control determining which network families a confined
application has access to.
Signed-off-by: John Johansen <jjohansen@suse.de>
---
security/apparmor/Makefile | 7 +
security/apparmor/apparmor.h | 9 ++
security/apparmor/lsm.c | 129 ++++++++++++++++++++++++++++++++++-
security/apparmor/main.c | 107 ++++++++++++++++++++++++++++-
security/apparmor/module_interface.c | 26 ++++++-
5 files changed, 271 insertions(+), 7 deletions(-)
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -8,6 +8,11 @@ apparmor-y := main.o list.o procattr.o l
quiet_cmd_make-caps = GEN $@
cmd_make-caps = sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z > $@
-$(obj)/main.o : $(obj)/capability_names.h
+quiet_cmd_make-af = GEN $@
+cmd_make-af = sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z > $@
+
+$(obj)/main.o : $(obj)/capability_names.h $(obj)/af_names.h
$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
$(call cmd,make-caps)
+$(obj)/af_names.h : $(srctree)/include/linux/socket.h
+ $(call cmd,make-af)
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -16,6 +16,8 @@
#include <linux/fs.h>
#include <linux/binfmts.h>
#include <linux/rcupdate.h>
+#include <linux/socket.h>
+#include <net/sock.h>
/*
* We use MAY_READ, MAY_WRITE, MAY_EXEC, MAY_APPEND and the following flags
@@ -208,6 +210,9 @@ struct aa_profile {
struct list_head task_contexts;
spinlock_t lock;
unsigned long int_flags;
+ u16 network_families[AF_MAX];
+ u16 audit_network[AF_MAX];
+ u16 quiet_network[AF_MAX];
};
extern struct list_head profile_ns_list;
@@ -254,6 +259,7 @@ struct aa_audit {
int request_mask, denied_mask, audit_mask;
struct iattr *iattr;
pid_t task, parent;
+ int family, type, protocol;
int error_code;
};
@@ -315,6 +321,9 @@ extern void aa_change_task_context(struc
struct aa_profile *previous_profile);
extern int aa_may_ptrace(struct aa_task_context *cxt,
struct aa_profile *tracee);
+extern int aa_net_perm(struct aa_profile *profile, char *operation,
+ int family, int type, int protocol);
+extern int aa_revalidate_sk(struct sock *sk, char *operation);
/* lsm.c */
extern int apparmor_initialized;
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -18,6 +18,7 @@
#include <linux/ctype.h>
#include <linux/sysctl.h>
#include <linux/audit.h>
+#include <net/sock.h>
#include "apparmor.h"
#include "inline.h"
@@ -663,6 +664,117 @@ static void apparmor_task_free_security(
aa_release(task);
}
+static int apparmor_socket_create(int family, int type, int protocol, int kern)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ if (kern)
+ return 0;
+
+ profile = aa_get_profile(current);
+ if (profile)
+ error = aa_net_perm(profile, "socket_create", family,
+ type, protocol);
+ aa_put_profile(profile);
+
+ return error;
+}
+
+static int apparmor_socket_post_create(struct socket *sock, int family,
+ int type, int protocol, int kern)
+{
+ struct sock *sk = sock->sk;
+
+ if (kern)
+ return 0;
+
+ return aa_revalidate_sk(sk, "socket_post_create");
+}
+
+static int apparmor_socket_bind(struct socket *sock,
+ struct sockaddr *address, int addrlen)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_bind");
+}
+
+static int apparmor_socket_connect(struct socket *sock,
+ struct sockaddr *address, int addrlen)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_connect");
+}
+
+static int apparmor_socket_listen(struct socket *sock, int backlog)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_listen");
+}
+
+static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_accept");
+}
+
+static int apparmor_socket_sendmsg(struct socket *sock,
+ struct msghdr *msg, int size)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_sendmsg");
+}
+
+static int apparmor_socket_recvmsg(struct socket *sock,
+ struct msghdr *msg, int size, int flags)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_recvmsg");
+}
+
+static int apparmor_socket_getsockname(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_getsockname");
+}
+
+static int apparmor_socket_getpeername(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_getpeername");
+}
+
+static int apparmor_socket_getsockopt(struct socket *sock, int level,
+ int optname)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_getsockopt");
+}
+
+static int apparmor_socket_setsockopt(struct socket *sock, int level,
+ int optname)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_setsockopt");
+}
+
+static int apparmor_socket_shutdown(struct socket *sock, int how)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_shutdown");
+}
+
static int apparmor_getprocattr(struct task_struct *task, char *name,
char **value)
{
@@ -763,9 +875,6 @@ struct security_operations apparmor_ops
.capable = apparmor_capable,
.syslog = cap_syslog,
- .netlink_send = cap_netlink_send,
- .netlink_recv = cap_netlink_recv,
-
.bprm_apply_creds = cap_bprm_apply_creds,
.bprm_set_security = apparmor_bprm_set_security,
.bprm_secureexec = apparmor_bprm_secureexec,
@@ -801,6 +910,20 @@ struct security_operations apparmor_ops
.getprocattr = apparmor_getprocattr,
.setprocattr = apparmor_setprocattr,
+
+ .socket_create = apparmor_socket_create,
+ .socket_post_create = apparmor_socket_post_create,
+ .socket_bind = apparmor_socket_bind,
+ .socket_connect = apparmor_socket_connect,
+ .socket_listen = apparmor_socket_listen,
+ .socket_accept = apparmor_socket_accept,
+ .socket_sendmsg = apparmor_socket_sendmsg,
+ .socket_recvmsg = apparmor_socket_recvmsg,
+ .socket_getsockname = apparmor_socket_getsockname,
+ .socket_getpeername = apparmor_socket_getpeername,
+ .socket_getsockopt = apparmor_socket_getsockopt,
+ .socket_setsockopt = apparmor_socket_setsockopt,
+ .socket_shutdown = apparmor_socket_shutdown,
};
void info_message(const char *str)
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -14,6 +14,9 @@
#include <linux/audit.h>
#include <linux/mount.h>
#include <linux/ptrace.h>
+#include <linux/socket.h>
+#include <linux/net.h>
+#include <net/sock.h>
#include "apparmor.h"
@@ -116,6 +119,24 @@ static void aa_audit_file_mask(struct au
audit_log_format(ab, " %s=\"%s::%s\"", name, user, other);
}
+static const char *address_families[] = {
+#include "af_names.h"
+};
+
+static const char *sock_types[] = {
+ "unknown(0)",
+ "stream",
+ "dgram",
+ "raw",
+ "rdm",
+ "seqpacket",
+ "dccp",
+ "unknown(7)",
+ "unknown(8)",
+ "unknown(9)",
+ "packet",
+};
+
/**
* aa_audit - Log an audit event to the audit subsystem
* @profile: profile to check against
@@ -187,7 +208,25 @@ static int aa_audit_base(struct aa_profi
audit_log_untrustedstring(ab, sa->name2);
}
- audit_log_format(ab, " pid=%d", current->pid);
+ if (sa->family || sa->type) {
+ if (address_families[sa->family])
+ audit_log_format(ab, " family=\"%s\"",
+ address_families[sa->family]);
+ else
+ audit_log_format(ab, " family=\"unknown(%d)\"",
+ sa->family);
+
+ if (sock_types[sa->type])
+ audit_log_format(ab, " sock_type=\"%s\"",
+ sock_types[sa->type]);
+ else
+ audit_log_format(ab, " sock_type=\"unknown(%d)\"",
+ sa->type);
+
+ audit_log_format(ab, " protocol=%d", sa->protocol);
+ }
+
+ audit_log_format(ab, " pid=%d", current->pid);
if (profile) {
audit_log_format(ab, " profile=");
@@ -768,6 +807,72 @@ int aa_link(struct aa_profile *profile,
return error;
}
+int aa_net_perm(struct aa_profile *profile, char *operation,
+ int family, int type, int protocol)
+{
+ struct aa_audit sa;
+ int error = 0;
+ u16 family_mask, audit_mask, quiet_mask;
+
+ if ((family < 0) || (family >= AF_MAX))
+ return -EINVAL;
+
+ if ((type < 0) || (type >= SOCK_MAX))
+ return -EINVAL;
+
+ /* unix domain and netlink sockets are handled by ipc */
+ if (family == AF_UNIX || family == AF_NETLINK)
+ return 0;
+
+ family_mask = profile->network_families[family];
+ audit_mask = profile->audit_network[family];
+ quiet_mask = profile->quiet_network[family];
+
+ error = (family_mask & (1 << type)) ? 0 : -EACCES;
+
+ memset(&sa, 0, sizeof(sa));
+ sa.operation = operation;
+ sa.gfp_mask = GFP_KERNEL;
+ sa.family = family;
+ sa.type = type;
+ sa.protocol = protocol;
+ sa.error_code = error;
+
+ if (likely(!error)) {
+ if (!PROFILE_AUDIT(profile) && !(family_mask & audit_mask))
+ return 0;
+ } else if (!((1 << type) & ~quiet_mask)) {
+ return error;
+ }
+
+ error = aa_audit(profile, &sa);
+
+ return error;
+}
+
+int aa_revalidate_sk(struct sock *sk, char *operation)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ /* this is some debugging code to flush out the network hooks that
+ that are called in interrupt context */
+ if (in_interrupt()) {
+ printk("AppArmor Debug: Hook being called from interrupt context\n");
+ dump_stack();
+ return 0;
+ }
+
+ profile = aa_get_profile(current);
+ if (profile)
+ error = aa_net_perm(profile, operation,
+ sk->sk_family, sk->sk_type,
+ sk->sk_protocol);
+ aa_put_profile(profile);
+
+ return error;
+}
+
/*******************************
* Global task related functions
*******************************/
--- a/security/apparmor/module_interface.c
+++ b/security/apparmor/module_interface.c
@@ -320,8 +320,8 @@ static struct aa_profile *aa_unpack_prof
struct aa_audit *sa)
{
struct aa_profile *profile = NULL;
-
- int error = -EPROTO;
+ size_t size = 0;
+ int i, error = -EPROTO;
profile = alloc_aa_profile();
if (!profile)
@@ -354,6 +354,28 @@ static struct aa_profile *aa_unpack_prof
if (!aa_is_u32(e, &(profile->set_caps), NULL))
goto fail;
+ size = aa_is_array(e, "net_allowed_af");
+ if (size) {
+ if (size > AF_MAX)
+ goto fail;
+
+ for (i = 0; i < size; i++) {
+ if (!aa_is_u16(e, &profile->network_families[i], NULL))
+ goto fail;
+ if (!aa_is_u16(e, &profile->audit_network[i], NULL))
+ goto fail;
+ if (!aa_is_u16(e, &profile->quiet_network[i], NULL))
+ goto fail;
+ }
+ if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
+ goto fail;
+ /* allow unix domain and netlink sockets they are handled
+ * by IPC
+ */
+ }
+ profile->network_families[AF_UNIX] = 0xffff;
+ profile->network_families[AF_NETLINK] = 0xffff;
+
/* get file rules */
profile->file_rules = aa_unpack_dfa(e);
if (IS_ERR(profile->file_rules)) {

View File

@@ -1,461 +0,0 @@
From: John Johansen <jjohansen@suse.de>
Subject: AppArmor: per profile controls for system rlimits
Provide contol of rlimits on a per profile basis. Each profile provides
a per limit contol and corresponding hard limit value, such that when a
profile becomes attached to a task it sets the tasks limits to be <= to
the profiles specified limits. Note: the profile limit value will not
raise a tasks limit if it is already less than the profile mandates.
In addition to setting a tasks limits, the ability to set limits on
a confined task are controlled. AppArmor only controls the raising
of a tasks limits Tasks with CAP_SYS_RESOURCE can have their hard limits
raised up to the value specified by the profile. AppArmor does not
prevent a task for lowering its hard limits, nor does it provide
additional control on soft limits.
AppArmor only controls the limits specified in a profile so that
any limit not specified is free to be modified subject to standard
linux limitations.
---
security/apparmor/apparmor.h | 23 ++++++
security/apparmor/apparmorfs.c | 2
security/apparmor/lsm.c | 16 ++++
security/apparmor/main.c | 132 +++++++++++++++++++++++++++++++----
security/apparmor/module_interface.c | 56 ++++++++++++++
5 files changed, 215 insertions(+), 14 deletions(-)
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -16,6 +16,7 @@
#include <linux/fs.h>
#include <linux/binfmts.h>
#include <linux/rcupdate.h>
+#include <linux/resource.h>
#include <linux/socket.h>
#include <net/sock.h>
@@ -136,6 +137,18 @@ extern unsigned int apparmor_path_max;
#define AA_ERROR(fmt, args...) printk(KERN_ERR "AppArmor: " fmt, ##args)
+/* struct aa_rlimit - rlimits settings for the profile
+ * @mask: which hard limits to set
+ * @limits: rlimit values that override task limits
+ *
+ * AppArmor rlimits are used to set confined task rlimits. Only the
+ * limits specified in @mask will be controlled by apparmor.
+ */
+struct aa_rlimit {
+ unsigned int mask;
+ struct rlimit limits[RLIM_NLIMITS];
+};
+
struct aa_profile;
/* struct aa_namespace - namespace for a set of profiles
@@ -170,6 +183,8 @@ struct aa_namespace {
* @audit_caps: caps that are to be audited
* @quiet_caps: caps that should not be audited
* @capabilities: capabilities granted by the process
+ * @rlimits: rlimits for the profile
+ * @task_count: how many tasks the profile is attached to
* @count: reference count of the profile
* @task_contexts: list of tasks confined by profile
* @lock: lock for the task_contexts list
@@ -206,6 +221,9 @@ struct aa_profile {
kernel_cap_t audit_caps;
kernel_cap_t quiet_caps;
+ struct aa_rlimit rlimits;
+ unsigned int task_count;
+
struct kref count;
struct list_head task_contexts;
spinlock_t lock;
@@ -257,6 +275,7 @@ struct aa_audit {
const char *name2;
const char *name3;
int request_mask, denied_mask, audit_mask;
+ int rlimit;
struct iattr *iattr;
pid_t task, parent;
int family, type, protocol;
@@ -324,6 +343,10 @@ extern int aa_may_ptrace(struct aa_task_
extern int aa_net_perm(struct aa_profile *profile, char *operation,
int family, int type, int protocol);
extern int aa_revalidate_sk(struct sock *sk, char *operation);
+extern int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
+ struct rlimit *new_rlim);
+extern void aa_set_rlimits(struct task_struct *task, struct aa_profile *profile);
+
/* lsm.c */
extern int apparmor_initialized;
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -105,7 +105,7 @@ static ssize_t aa_features_read(struct f
{
const char *features = "file=3.0 capability=2.0 network=1.0 "
"change_hat=1.4 change_profile=1.0 "
- "aanamespaces=1.0";
+ "aanamespaces=1.0 rlimit=1.0";
return simple_read_from_buffer(buf, size, ppos, features,
strlen(features));
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -866,6 +866,21 @@ static int apparmor_setprocattr(struct t
return error;
}
+static int apparmor_task_setrlimit(unsigned int resource,
+ struct rlimit *new_rlim)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ profile = aa_get_profile(current);
+ if (profile) {
+ error = aa_task_setrlimit(profile, resource, new_rlim);
+ }
+ aa_put_profile(profile);
+
+ return error;
+}
+
struct security_operations apparmor_ops = {
.ptrace = apparmor_ptrace,
.capget = cap_capget,
@@ -907,6 +922,7 @@ struct security_operations apparmor_ops
.task_free_security = apparmor_task_free_security,
.task_post_setuid = cap_task_post_setuid,
.task_reparent_to_init = cap_task_reparent_to_init,
+ .task_setrlimit = apparmor_task_setrlimit,
.getprocattr = apparmor_getprocattr,
.setprocattr = apparmor_setprocattr,
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -177,6 +177,9 @@ static int aa_audit_base(struct aa_profi
if (sa->request_mask)
audit_log_format(ab, " fsuid=%d", current->fsuid);
+ if (sa->rlimit)
+ audit_log_format(ab, " rlimit=%d", sa->rlimit - 1);
+
if (sa->iattr) {
struct iattr *iattr = sa->iattr;
@@ -872,6 +875,79 @@ int aa_revalidate_sk(struct sock *sk, ch
return error;
}
+/**
+ * aa_task_setrlimit - test permission to set an rlimit
+ * @profile - profile confining the task
+ * @resource - the resource being set
+ * @new_rlim - the new resource limit
+ *
+ * Control raising the processes hard limit.
+ */
+int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
+ struct rlimit *new_rlim)
+{
+ struct aa_audit sa;
+ int error = 0;
+
+ memset(&sa, 0, sizeof(sa));
+ sa.operation = "setrlimit";
+ sa.gfp_mask = GFP_KERNEL;
+ sa.rlimit = resource + 1;
+
+ if (profile->rlimits.mask & (1 << resource) &&
+ new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max) {
+ sa.error_code = -EACCES;
+
+ error = aa_audit(profile, &sa);
+ }
+
+ return error;
+}
+
+static int aa_rlimit_nproc(struct aa_profile *profile) {
+ if (profile && (profile->rlimits.mask & (1 << RLIMIT_NPROC)) &&
+ profile->task_count >= profile->rlimits.limits[RLIMIT_NPROC].rlim_max)
+ return -EAGAIN;
+ return 0;
+}
+
+void aa_set_rlimits(struct task_struct *task, struct aa_profile *profile)
+{
+ int i, mask;
+
+ if (!profile)
+ return;
+
+ if (!profile->rlimits.mask)
+ return;
+
+ task_lock(task->group_leader);
+ mask = 1;
+ for (i = 0; i < RLIM_NLIMITS; i++, mask <<= 1) {
+ struct rlimit new_rlim, *old_rlim;
+
+ /* check to see if NPROC which is per profile and handled
+ * in clone/exec or whether this is a limit to be set
+ * can't set cpu limit either right now
+ */
+ if (i == RLIMIT_NPROC || i == RLIMIT_CPU)
+ continue;
+
+ old_rlim = task->signal->rlim + i;
+ new_rlim = *old_rlim;
+
+ if (mask & profile->rlimits.mask &&
+ profile->rlimits.limits[i].rlim_max < new_rlim.rlim_max) {
+ new_rlim.rlim_max = profile->rlimits.limits[i].rlim_max;
+ /* soft limit should not exceed hard limit */
+ if (new_rlim.rlim_cur > new_rlim.rlim_max)
+ new_rlim.rlim_cur = new_rlim.rlim_max;
+ }
+
+ *old_rlim = new_rlim;
+ }
+ task_unlock(task->group_leader);
+}
/*******************************
* Global task related functions
@@ -885,6 +961,7 @@ int aa_revalidate_sk(struct sock *sk, ch
*/
int aa_clone(struct task_struct *child)
{
+ struct aa_audit sa;
struct aa_task_context *cxt, *child_cxt;
struct aa_profile *profile;
@@ -894,6 +971,11 @@ int aa_clone(struct task_struct *child)
if (!child_cxt)
return -ENOMEM;
+ memset(&sa, 0, sizeof(sa));
+ sa.operation = "clone";
+ sa.task = child->pid;
+ sa.gfp_mask = GFP_KERNEL;
+
repeat:
profile = aa_get_profile(current);
if (profile) {
@@ -910,18 +992,22 @@ repeat:
goto repeat;
}
+ if (aa_rlimit_nproc(profile)) {
+ sa.info = "rlimit nproc limit exceeded";
+ unlock_profile(profile);
+ aa_audit_reject(profile, &sa);
+ aa_put_profile(profile);
+ return -EAGAIN;
+ }
+
/* No need to grab the child's task lock here. */
aa_change_task_context(child, child_cxt, profile,
cxt->cookie, cxt->previous_profile);
+
unlock_profile(profile);
if (APPARMOR_COMPLAIN(child_cxt) &&
profile == profile->ns->null_complain_profile) {
- struct aa_audit sa;
- memset(&sa, 0, sizeof(sa));
- sa.operation = "clone";
- sa.gfp_mask = GFP_KERNEL;
- sa.task = child->pid;
aa_audit_hint(profile, &sa);
}
aa_put_profile(profile);
@@ -1156,6 +1242,10 @@ repeat:
sa.task = current->parent->pid;
aa_audit_reject(profile, &sa);
}
+ if (PTR_ERR(old_profile) == -EAGAIN) {
+ sa.info = "rlimit nproc limit exceeded";
+ aa_audit_reject(profile, &sa);
+ }
new_profile = old_profile;
goto cleanup;
}
@@ -1296,6 +1386,12 @@ static int do_change_profile(struct aa_p
goto out;
}
+ if ((error = aa_rlimit_nproc(new_profile))) {
+ sa->info = "rlimit nproc limit exceeded";
+ aa_audit_reject(cxt->profile, sa);
+ goto out;
+ }
+
if (new_profile == ns->null_complain_profile)
aa_audit_hint(cxt->profile, sa);
@@ -1482,17 +1578,18 @@ struct aa_profile *__aa_replace_profile(
cxt = lock_task_and_profiles(task, profile);
if (unlikely(profile && profile->isstale)) {
- task_unlock(task);
- unlock_both_profiles(profile, cxt ? cxt->profile : NULL);
- aa_free_task_context(new_cxt);
- return ERR_PTR(-ESTALE);
+ old_profile = ERR_PTR(-ESTALE);
+ goto error;
}
if ((current->ptrace & PT_PTRACED) && aa_may_ptrace(cxt, profile)) {
- task_unlock(task);
- unlock_both_profiles(profile, cxt ? cxt->profile : NULL);
- aa_free_task_context(new_cxt);
- return ERR_PTR(-EPERM);
+ old_profile = ERR_PTR(-EPERM);
+ goto error;
+ }
+
+ if (aa_rlimit_nproc(profile)) {
+ old_profile = ERR_PTR(-EAGAIN);
+ goto error;
}
if (cxt)
@@ -1500,8 +1597,15 @@ struct aa_profile *__aa_replace_profile(
aa_change_task_context(task, new_cxt, profile, 0, NULL);
task_unlock(task);
+ aa_set_rlimits(task, profile);
unlock_both_profiles(profile, old_profile);
return old_profile;
+
+error:
+ task_unlock(task);
+ unlock_both_profiles(profile, cxt ? cxt->profile : NULL);
+ aa_free_task_context(new_cxt);
+ return old_profile;
}
/**
@@ -1566,6 +1670,7 @@ void aa_change_task_context(struct task_
if (old_cxt) {
list_del_init(&old_cxt->list);
+ old_cxt->profile->task_count--;
call_rcu(&old_cxt->rcu, free_aa_task_context_rcu_callback);
}
if (new_cxt) {
@@ -1577,6 +1682,7 @@ void aa_change_task_context(struct task_
new_cxt->cookie = cookie;
new_cxt->task = task;
new_cxt->profile = aa_dup_profile(profile);
+ profile->task_count++;
new_cxt->previous_profile = aa_dup_profile(previous_profile);
list_move(&new_cxt->list, &profile->task_contexts);
}
--- a/security/apparmor/module_interface.c
+++ b/security/apparmor/module_interface.c
@@ -177,6 +177,22 @@ fail:
return 0;
}
+static int aa_is_u64(struct aa_ext *e, u64 *data, const char *name)
+{
+ void *pos = e->pos;
+ if (aa_is_nameX(e, AA_U64, name)) {
+ if (!aa_inbounds(e, sizeof(u64)))
+ goto fail;
+ if (data)
+ *data = le64_to_cpu(get_unaligned((u64 *)e->pos));
+ e->pos += sizeof(u64);
+ return 1;
+ }
+fail:
+ e->pos = pos;
+ return 0;
+}
+
static size_t aa_is_array(struct aa_ext *e, const char *name)
{
void *pos = e->pos;
@@ -311,6 +327,39 @@ fail:
return 0;
}
+int aa_unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
+{
+ void *pos = e->pos;
+
+ /* rlimits are optional */
+ if (aa_is_nameX(e, AA_STRUCT, "rlimits")) {
+ int i, size;
+ u32 tmp = 0;
+ if (!aa_is_u32(e, &tmp, NULL))
+ goto fail;
+ profile->rlimits.mask = tmp;
+
+ size = aa_is_array(e, NULL);
+ if (size != RLIM_NLIMITS)
+ goto fail;
+ for (i = 0; i < size; i++) {
+ u64 tmp = 0;
+ if (!aa_is_u64(e, &tmp, NULL))
+ goto fail;
+ profile->rlimits.limits[i].rlim_max = tmp;
+ }
+ if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
+ goto fail;
+ if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
+ goto fail;
+ }
+ return 1;
+
+fail:
+ e->pos = pos;
+ return 0;
+}
+
/**
* aa_unpack_profile - unpack a serialized profile
* @e: serialized data extent information
@@ -354,6 +403,9 @@ static struct aa_profile *aa_unpack_prof
if (!aa_is_u32(e, &(profile->set_caps), NULL))
goto fail;
+ if (!aa_unpack_rlimits(e, profile))
+ goto fail;
+
size = aa_is_array(e, "net_allowed_af");
if (size) {
if (size > AF_MAX)
@@ -613,6 +665,8 @@ ssize_t aa_replace_profile(void *udata,
sa.operation = "profile_load";
goto out;
}
+ /* do not fail replacement based off of profile's NPROC rlimit */
+
/*
* Replacement needs to allocate a new aa_task_context for each
* task confined by old_profile. To do this the profile locks
@@ -633,6 +687,7 @@ ssize_t aa_replace_profile(void *udata,
task_lock(task);
task_replace(task, new_cxt, new_profile);
task_unlock(task);
+ aa_set_rlimits(task, new_profile);
new_cxt = NULL;
}
unlock_both_profiles(old_profile, new_profile);
@@ -655,6 +710,7 @@ out:
*
* remove a profile from the profile list and all aa_task_context references
* to said profile.
+ * NOTE: removing confinement does not restore rlimits to preconfinemnet values
*/
ssize_t aa_remove_profile(char *name, size_t size)
{

View File

@@ -1,18 +0,0 @@
---
security/apparmor/main.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -159,8 +159,10 @@ static int aa_audit_base(struct aa_profi
return type == AUDIT_APPARMOR_ALLOWED ? 0 : -ENOMEM;
}
+ audit_log_format(ab, " type=%d", type);
+
if (sa->operation)
- audit_log_format(ab, "operation=\"%s\"", sa->operation);
+ audit_log_format(ab, " operation=\"%s\"", sa->operation);
if (sa->info) {
audit_log_format(ab, " info=\"%s\"", sa->info);

View File

@@ -1,86 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Add d_namespace_path() to compute namespace relative pathnames
In AppArmor, we are interested in pathnames relative to the namespace root.
This is the same as d_path() except for the root where the search ends. Add
a function for computing the namespace-relative path.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/dcache.c | 6 +++---
fs/namespace.c | 27 +++++++++++++++++++++++++++
include/linux/dcache.h | 2 ++
include/linux/mount.h | 2 ++
4 files changed, 34 insertions(+), 3 deletions(-)
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1782,9 +1782,9 @@ shouldnt_be_hashed:
*
* 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, int fail_deleted)
+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, vfsmount_locked = 0;
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1883,3 +1883,30 @@ void __put_mnt_ns(struct mnt_namespace *
release_mounts(&umount_list);
kfree(ns);
}
+
+char *d_namespace_path(struct dentry *dentry, struct vfsmount *vfsmnt,
+ char *buf, int buflen)
+{
+ struct vfsmount *rootmnt, *nsrootmnt = NULL;
+ struct dentry *root = NULL;
+ char *res;
+
+ read_lock(&current->fs->lock);
+ rootmnt = mntget(current->fs->rootmnt);
+ read_unlock(&current->fs->lock);
+ spin_lock(&vfsmount_lock);
+ if (rootmnt->mnt_ns)
+ nsrootmnt = mntget(rootmnt->mnt_ns->root);
+ spin_unlock(&vfsmount_lock);
+ mntput(rootmnt);
+ if (nsrootmnt)
+ root = dget(nsrootmnt->mnt_root);
+ res = __d_path(dentry, vfsmnt, root, nsrootmnt, buf, buflen, 1);
+ dput(root);
+ mntput(nsrootmnt);
+ /* Prevent empty path for lazily unmounted filesystems. */
+ if (!IS_ERR(res) && *res == '\0')
+ *--res = '.';
+ return res;
+}
+EXPORT_SYMBOL(d_namespace_path);
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -300,6 +300,8 @@ extern int d_validate(struct dentry *, s
*/
extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
+extern char *__d_path(struct dentry *, struct vfsmount *, struct dentry *,
+ struct vfsmount *, char *, int, int);
extern char * d_path(struct dentry *, struct vfsmount *, char *, int);
/* Allocation counts.. */
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -103,5 +103,7 @@ extern void shrink_submounts(struct vfsm
extern spinlock_t vfsmount_lock;
extern dev_t name_to_dev_t(char *name);
+extern char *d_namespace_path(struct dentry *, struct vfsmount *, char *, int);
+
#endif
#endif /* _LINUX_MOUNT_H */

View File

@@ -1,47 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Switch to vfs_permission() in do_path_lookup()
Switch from file_permission() to vfs_permission() in do_path_lookup():
this avoids calling permission() with a NULL nameidata here.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1147,25 +1147,24 @@ static int fastcall do_path_lookup(int d
nd->dentry = dget(fs->pwd);
read_unlock(&fs->lock);
} else {
- struct dentry *dentry;
-
file = fget_light(dfd, &fput_needed);
retval = -EBADF;
if (!file)
goto out_fail;
- dentry = file->f_path.dentry;
+ nd->dentry = file->f_path.dentry;
+ nd->mnt = file->f_path.mnt;
retval = -ENOTDIR;
- if (!S_ISDIR(dentry->d_inode->i_mode))
+ if (!S_ISDIR(nd->dentry->d_inode->i_mode))
goto fput_fail;
- retval = file_permission(file, MAY_EXEC);
+ retval = vfs_permission(nd, MAY_EXEC);
if (retval)
goto fput_fail;
- nd->mnt = mntget(file->f_path.mnt);
- nd->dentry = dget(dentry);
+ mntget(nd->mnt);
+ dget(nd->dentry);
fput_light(file, fput_needed);
}

View File

@@ -1,83 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Enable LSM hooks to distinguish operations on file descriptors from operations on pathnames
Struct iattr already contains ia_file since commit cc4e69de from
Miklos (which is related to commit befc649c). Use this to pass
struct file down the setattr hooks. This allows LSMs to distinguish
operations on file descriptors from operations on paths.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
Cc: Miklos Szeredi <mszeredi@suse.cz>
---
fs/nfsd/vfs.c | 12 +++++++-----
fs/open.c | 4 +++-
2 files changed, 10 insertions(+), 6 deletions(-)
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -413,7 +413,7 @@ static ssize_t nfsd_getxattr(struct dent
{
ssize_t buflen;
- buflen = vfs_getxattr(dentry, mnt, key, NULL, 0);
+ buflen = vfs_getxattr(dentry, mnt, key, NULL, 0, NULL);
if (buflen <= 0)
return buflen;
@@ -421,7 +421,7 @@ static ssize_t nfsd_getxattr(struct dent
if (!*buf)
return -ENOMEM;
- return vfs_getxattr(dentry, mnt, key, *buf, buflen);
+ return vfs_getxattr(dentry, mnt, key, *buf, buflen, NULL);
}
#endif
@@ -447,7 +447,7 @@ set_nfsv4_acl_one(struct dentry *dentry,
goto out;
}
- error = vfs_setxattr(dentry, mnt, key, buf, len, 0);
+ error = vfs_setxattr(dentry, mnt, key, buf, len, 0, NULL);
out:
kfree(buf);
return error;
@@ -2051,12 +2051,14 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i
mnt = fhp->fh_export->ex_mnt;
if (size)
- error = vfs_setxattr(fhp->fh_dentry, mnt, name, value, size,0);
+ error = vfs_setxattr(fhp->fh_dentry, mnt, name, value, size, 0,
+ NULL);
else {
if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
error = 0;
else {
- error = vfs_removexattr(fhp->fh_dentry, mnt, name);
+ error = vfs_removexattr(fhp->fh_dentry, mnt, name,
+ NULL);
if (error == -ENODATA)
error = 0;
}
--- a/fs/open.c
+++ b/fs/open.c
@@ -581,7 +581,7 @@ asmlinkage long sys_fchmod(unsigned int
if (mode == (mode_t) -1)
mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
- newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+ newattrs.ia_valid = ATTR_MODE | ATTR_CTIME | ATTR_FILE;
err = fnotify_change(dentry, file->f_path.mnt, &newattrs, file);
mutex_unlock(&inode->i_mutex);
@@ -661,6 +661,8 @@ static int chown_common(struct dentry *
if (!S_ISDIR(inode->i_mode))
newattrs.ia_valid |=
ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
+ if (file)
+ newattrs.ia_valid |= ATTR_FILE;
mutex_lock(&inode->i_mutex);
error = fnotify_change(dentry, mnt, &newattrs, file);
mutex_unlock(&inode->i_mutex);

View File

@@ -1,31 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Fix file_permission()
We cannot easily switch from file_permission() to vfs_permission()
everywhere, so fix file_permission() to not use a NULL nameidata
for the remaining users.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -313,7 +313,13 @@ int vfs_permission(struct nameidata *nd,
*/
int file_permission(struct file *file, int mask)
{
- return permission(file->f_path.dentry->d_inode, mask, NULL);
+ struct nameidata nd;
+
+ nd.dentry = file->f_path.dentry;
+ nd.mnt = file->f_path.mnt;
+ nd.flags = LOOKUP_ACCESS;
+
+ return permission(nd.dentry->d_inode, mask, &nd);
}
/*

View File

@@ -1,44 +0,0 @@
From: John Johansen <jjohansen@suse.de>
Subject: 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 <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
fs/namei.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2097,6 +2097,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);
@@ -2104,12 +2108,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) {

View File

@@ -1,27 +0,0 @@
---
fs/open.c | 3 +++
include/linux/fs.h | 1 +
2 files changed, 4 insertions(+)
--- a/fs/open.c
+++ b/fs/open.c
@@ -207,6 +207,9 @@ int do_truncate(struct dentry *dentry, s
newattrs.ia_size = length;
newattrs.ia_valid = ATTR_SIZE | time_attrs;
+ if (filp)
+ newattrs.ia_valid |= ATTR_FILE;
+
/* Remove suid/sgid on truncate too */
newattrs.ia_valid |= should_remove_suid(dentry);
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -329,6 +329,7 @@ typedef void (dio_iodone_t)(struct kiocb
#define ATTR_ATTR_FLAG 1024
#define ATTR_KILL_SUID 2048
#define ATTR_KILL_SGID 4096
+#define ATTR_FILE 8192
#define ATTR_KILL_PRIV 16384
#define ATTR_OPEN 32768 /* Truncating from open(O_TRUNC) */

View File

@@ -1,392 +0,0 @@
Subject: VFS: new fsetattr() file operation
From: Miklos Szeredi <mszeredi@suse.cz>
Add a new file operation: f_op->fsetattr(), that is invoked by
ftruncate, fchmod, fchown and utimensat. Fall back to i_op->setattr()
if it is not defined.
For the reasons why we need this, see patch adding fgetattr().
ftruncate() already passed the open file to the filesystem via the
ia_file member of struct iattr. However it is cleaner to have a
separate file operation for this, so remove ia_file, ATTR_FILE and
convert existing users: fuse and AFS.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> ---
Signed-off-by: John Johansen <jjohansen@suse.de> ---
---
fs/afs/dir.c | 1 +
fs/afs/file.c | 1 +
fs/afs/inode.c | 19 +++++++++++++++----
fs/afs/internal.h | 1 +
fs/attr.c | 18 ++++++++++++++----
fs/fuse/dir.c | 20 +++++++++-----------
fs/fuse/file.c | 7 +++++++
fs/fuse/fuse_i.h | 4 ++++
fs/open.c | 20 ++++++++------------
fs/utimes.c | 2 +-
include/linux/fs.h | 10 ++--------
11 files changed, 63 insertions(+), 40 deletions(-)
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -45,6 +45,7 @@ const struct file_operations afs_dir_fil
.release = afs_release,
.readdir = afs_readdir,
.lock = afs_lock,
+ .fsetattr = afs_fsetattr,
};
const struct inode_operations afs_dir_inode_operations = {
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -36,6 +36,7 @@ const struct file_operations afs_file_op
.fsync = afs_fsync,
.lock = afs_lock,
.flock = afs_flock,
+ .fsetattr = afs_fsetattr,
};
const struct inode_operations afs_file_inode_operations = {
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -360,7 +360,8 @@ void afs_clear_inode(struct inode *inode
/*
* set the attributes of an inode
*/
-int afs_setattr(struct dentry *dentry, struct iattr *attr)
+static int afs_do_setattr(struct dentry *dentry, struct iattr *attr,
+ struct file *file)
{
struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
struct key *key;
@@ -382,8 +383,8 @@ int afs_setattr(struct dentry *dentry, s
afs_writeback_all(vnode);
}
- if (attr->ia_valid & ATTR_FILE) {
- key = attr->ia_file->private_data;
+ if (file) {
+ key = file->private_data;
} else {
key = afs_request_key(vnode->volume->cell);
if (IS_ERR(key)) {
@@ -393,10 +394,20 @@ int afs_setattr(struct dentry *dentry, s
}
ret = afs_vnode_setattr(vnode, key, attr);
- if (!(attr->ia_valid & ATTR_FILE))
+ if (!file)
key_put(key);
error:
_leave(" = %d", ret);
return ret;
}
+
+int afs_setattr(struct dentry *dentry, struct iattr *attr)
+{
+ return afs_do_setattr(dentry, attr, NULL);
+}
+
+int afs_fsetattr(struct file *file, struct iattr *attr)
+{
+ return afs_do_setattr(file->f_path.dentry, attr, file);
+}
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -550,6 +550,7 @@ extern void afs_zap_data(struct afs_vnod
extern int afs_validate(struct afs_vnode *, struct key *);
extern int afs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
extern int afs_setattr(struct dentry *, struct iattr *);
+extern int afs_fsetattr(struct file *, struct iattr *);
extern void afs_clear_inode(struct inode *);
/*
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -100,8 +100,8 @@ int inode_setattr(struct inode * inode,
}
EXPORT_SYMBOL(inode_setattr);
-int notify_change(struct dentry *dentry, struct vfsmount *mnt,
- struct iattr *attr)
+int fnotify_change(struct dentry *dentry, struct vfsmount *mnt,
+ struct iattr *attr, struct file *file)
{
struct inode *inode = dentry->d_inode;
mode_t mode = inode->i_mode;
@@ -160,8 +160,12 @@ int notify_change(struct dentry *dentry,
if (inode->i_op && inode->i_op->setattr) {
error = security_inode_setattr(dentry, mnt, attr);
- if (!error)
- error = inode->i_op->setattr(dentry, attr);
+ if (!error) {
+ if (file && file->f_op && file->f_op->fsetattr)
+ error = file->f_op->fsetattr(file, attr);
+ else
+ error = inode->i_op->setattr(dentry, attr);
+ }
} else {
error = inode_change_ok(inode, attr);
if (!error)
@@ -184,4 +188,10 @@ int notify_change(struct dentry *dentry,
return error;
}
+int notify_change(struct dentry *dentry, struct vfsmount *mnt,
+ struct iattr *attr)
+{
+ return fnotify_change(dentry, mnt, attr, NULL);
+}
+
EXPORT_SYMBOL(notify_change);
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1063,21 +1063,22 @@ static int fuse_dir_fsync(struct file *f
return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
}
-static bool update_mtime(unsigned ivalid)
+static bool update_mtime(unsigned ivalid, bool have_file)
{
/* Always update if mtime is explicitly set */
if (ivalid & ATTR_MTIME_SET)
return true;
/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
- if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
+ if ((ivalid & ATTR_SIZE) && ((ivalid & ATTR_OPEN) || have_file))
return false;
/* In all other cases update */
return true;
}
-static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
+static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg,
+ bool have_file)
{
unsigned ivalid = iattr->ia_valid;
@@ -1096,7 +1097,7 @@ static void iattr_to_fattr(struct iattr
if (!(ivalid & ATTR_ATIME_SET))
arg->valid |= FATTR_ATIME_NOW;
}
- if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
+ if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, have_file)) {
arg->valid |= FATTR_MTIME;
arg->mtime = iattr->ia_mtime.tv_sec;
arg->mtimensec = iattr->ia_mtime.tv_nsec;
@@ -1113,8 +1114,8 @@ static void iattr_to_fattr(struct iattr
* vmtruncate() doesn't allow for this case, so do the rlimit checking
* and the actual truncation by hand.
*/
-static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
- struct file *file)
+int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
+ struct file *file)
{
struct inode *inode = entry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
@@ -1152,7 +1153,7 @@ static int fuse_do_setattr(struct dentry
memset(&inarg, 0, sizeof(inarg));
memset(&outarg, 0, sizeof(outarg));
- iattr_to_fattr(attr, &inarg);
+ iattr_to_fattr(attr, &inarg, file != NULL);
if (file) {
struct fuse_file *ff = file->private_data;
inarg.valid |= FATTR_FH;
@@ -1194,10 +1195,7 @@ static int fuse_do_setattr(struct dentry
static int fuse_setattr(struct dentry *entry, struct iattr *attr)
{
- if (attr->ia_valid & ATTR_FILE)
- return fuse_do_setattr(entry, attr, attr->ia_file);
- else
- return fuse_do_setattr(entry, attr, NULL);
+ return fuse_do_setattr(entry, attr, NULL);
}
static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -907,6 +907,11 @@ static sector_t fuse_bmap(struct address
return err ? 0 : outarg.block;
}
+static int fuse_fsetattr(struct file *file, struct iattr *attr)
+{
+ return fuse_do_setattr(file->f_path.dentry, attr, file);
+}
+
static const struct file_operations fuse_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
@@ -920,6 +925,7 @@ static const struct file_operations fuse
.fsync = fuse_fsync,
.lock = fuse_file_lock,
.flock = fuse_file_flock,
+ .fsetattr = fuse_fsetattr,
.splice_read = generic_file_splice_read,
};
@@ -933,6 +939,7 @@ static const struct file_operations fuse
.fsync = fuse_fsync,
.lock = fuse_file_lock,
.flock = fuse_file_flock,
+ .fsetattr = fuse_fsetattr,
/* no mmap and splice_read */
};
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -505,6 +505,10 @@ void fuse_change_attributes(struct inode
*/
int fuse_dev_init(void);
+
+int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
+ struct file *file);
+
/**
* Cleanup the client device
*/
--- a/fs/open.c
+++ b/fs/open.c
@@ -206,16 +206,12 @@ int do_truncate(struct dentry *dentry, s
newattrs.ia_size = length;
newattrs.ia_valid = ATTR_SIZE | time_attrs;
- if (filp) {
- newattrs.ia_file = filp;
- newattrs.ia_valid |= ATTR_FILE;
- }
/* Remove suid/sgid on truncate too */
newattrs.ia_valid |= should_remove_suid(dentry);
mutex_lock(&dentry->d_inode->i_mutex);
- err = notify_change(dentry, mnt, &newattrs);
+ err = fnotify_change(dentry, mnt, &newattrs, filp);
mutex_unlock(&dentry->d_inode->i_mutex);
return err;
}
@@ -583,7 +579,7 @@ asmlinkage long sys_fchmod(unsigned int
mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
- err = notify_change(dentry, file->f_path.mnt, &newattrs);
+ err = fnotify_change(dentry, file->f_path.mnt, &newattrs, file);
mutex_unlock(&inode->i_mutex);
out_putf:
@@ -633,7 +629,7 @@ asmlinkage long sys_chmod(const char __u
}
static int chown_common(struct dentry * dentry, struct vfsmount *mnt,
- uid_t user, gid_t group)
+ uid_t user, gid_t group, struct file *file)
{
struct inode * inode;
int error;
@@ -663,7 +659,7 @@ static int chown_common(struct dentry *
newattrs.ia_valid |=
ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
mutex_lock(&inode->i_mutex);
- error = notify_change(dentry, mnt, &newattrs);
+ error = fnotify_change(dentry, mnt, &newattrs, file);
mutex_unlock(&inode->i_mutex);
out:
return error;
@@ -677,7 +673,7 @@ asmlinkage long sys_chown(const char __u
error = user_path_walk(filename, &nd);
if (error)
goto out;
- error = chown_common(nd.dentry, nd.mnt, user, group);
+ error = chown_common(nd.dentry, nd.mnt, user, group, NULL);
path_release(&nd);
out:
return error;
@@ -697,7 +693,7 @@ asmlinkage long sys_fchownat(int dfd, co
error = __user_walk_fd(dfd, filename, follow, &nd);
if (error)
goto out;
- error = chown_common(nd.dentry, nd.mnt, user, group);
+ error = chown_common(nd.dentry, nd.mnt, user, group, NULL);
path_release(&nd);
out:
return error;
@@ -711,7 +707,7 @@ asmlinkage long sys_lchown(const char __
error = user_path_walk_link(filename, &nd);
if (error)
goto out;
- error = chown_common(nd.dentry, nd.mnt, user, group);
+ error = chown_common(nd.dentry, nd.mnt, user, group, NULL);
path_release(&nd);
out:
return error;
@@ -730,7 +726,7 @@ asmlinkage long sys_fchown(unsigned int
dentry = file->f_path.dentry;
audit_inode(NULL, dentry);
- error = chown_common(dentry, file->f_path.mnt, user, group);
+ error = chown_common(dentry, file->f_path.mnt, user, group, file);
fput(file);
out:
return error;
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -132,7 +132,7 @@ long do_utimes(int dfd, char __user *fil
}
}
mutex_lock(&inode->i_mutex);
- error = notify_change(path.dentry, path.mnt, &newattrs);
+ error = fnotify_change(path.dentry, path.mnt, &newattrs, f);
mutex_unlock(&inode->i_mutex);
dput_and_out:
if (f)
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -329,7 +329,6 @@ typedef void (dio_iodone_t)(struct kiocb
#define ATTR_ATTR_FLAG 1024
#define ATTR_KILL_SUID 2048
#define ATTR_KILL_SGID 4096
-#define ATTR_FILE 8192
#define ATTR_KILL_PRIV 16384
#define ATTR_OPEN 32768 /* Truncating from open(O_TRUNC) */
@@ -351,13 +350,6 @@ struct iattr {
struct timespec ia_atime;
struct timespec ia_mtime;
struct timespec ia_ctime;
-
- /*
- * Not an attribute, but an auxilary info for filesystems wanting to
- * implement an ftruncate() like method. NOTE: filesystem should
- * check for (ia_valid & ATTR_FILE), and not for (ia_file != NULL).
- */
- struct file *ia_file;
};
/*
@@ -1188,6 +1180,7 @@ struct file_operations {
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
int (*setlease)(struct file *, long, struct file_lock **);
+ int (*fsetattr)(struct file *, struct iattr *);
};
struct inode_operations {
@@ -1694,6 +1687,7 @@ extern int do_remount_sb(struct super_bl
extern sector_t bmap(struct inode *, sector_t);
#endif
extern int notify_change(struct dentry *, struct vfsmount *, struct iattr *);
+extern int fnotify_change(struct dentry *, struct vfsmount *, struct iattr *, struct file *);
extern int permission(struct inode *, int, struct nameidata *);
extern int generic_permission(struct inode *, int,
int (*check_acl)(struct inode *, int));

View File

@@ -1,60 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Make d_path() consistent across mount operations
The path that __d_path() computes can become slightly inconsistent when it
races with mount operations: it grabs the vfsmount_lock when traversing mount
points but immediately drops it again, only to re-grab it when it reaches the
next mount point. The result is that the filename computed is not always
consisent, and the file may never have had that name. (This is unlikely, but
still possible.)
Fix this by grabbing the vfsmount_lock when the first mount point is reached,
and holding onto it until the d_cache lookup is completed.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/dcache.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1786,7 +1786,7 @@ static char *__d_path(struct dentry *den
struct dentry *root, struct vfsmount *rootmnt,
char *buffer, int buflen, int fail_deleted)
{
- int namelen, is_slash;
+ int namelen, is_slash, vfsmount_locked = 0;
if (buflen < 2)
return ERR_PTR(-ENAMETOOLONG);
@@ -1809,14 +1809,14 @@ static char *__d_path(struct dentry *den
struct dentry * parent;
if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
- spin_lock(&vfsmount_lock);
- if (vfsmnt->mnt_parent == vfsmnt) {
- spin_unlock(&vfsmount_lock);
- goto global_root;
+ if (!vfsmount_locked) {
+ spin_lock(&vfsmount_lock);
+ vfsmount_locked = 1;
}
+ if (vfsmnt->mnt_parent == vfsmnt)
+ goto global_root;
dentry = vfsmnt->mnt_mountpoint;
vfsmnt = vfsmnt->mnt_parent;
- spin_unlock(&vfsmount_lock);
continue;
}
parent = dentry->d_parent;
@@ -1835,6 +1835,8 @@ static char *__d_path(struct dentry *den
*--buffer = '/';
out:
+ if (vfsmount_locked)
+ spin_unlock(&vfsmount_lock);
spin_unlock(&dcache_lock);
return buffer;

View File

@@ -1,24 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Allow permission functions to tell between parent and leaf checks
Set the LOOKUP_CONTINUE flag when checking parent permissions. This allows
permission functions to tell between parent and leaf checks.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 2 ++
1 file changed, 2 insertions(+)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1508,6 +1508,8 @@ static inline int may_create(struct inod
return -EEXIST;
if (IS_DEADDIR(dir))
return -ENOENT;
+ if (nd)
+ nd->flags |= LOOKUP_CONTINUE;
return permission(dir,MAY_WRITE | MAY_EXEC, nd);
}

View File

@@ -1,144 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Pass struct path down to remove_suid and children
Required by a later patch that adds a struct vfsmount parameter to
notify_change().
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/ntfs/file.c | 2 +-
fs/splice.c | 4 ++--
fs/xfs/linux-2.6/xfs_lrw.c | 2 +-
include/linux/fs.h | 4 ++--
mm/filemap.c | 16 ++++++++--------
mm/filemap_xip.c | 2 +-
mm/shmem.c | 2 +-
7 files changed, 16 insertions(+), 16 deletions(-)
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -2120,7 +2120,7 @@ static ssize_t ntfs_file_aio_write_noloc
goto out;
if (!count)
goto out;
- err = remove_suid(file->f_path.dentry);
+ err = remove_suid(&file->f_path);
if (err)
goto out;
file_update_time(file);
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -775,7 +775,7 @@ generic_file_splice_write_nolock(struct
ssize_t ret;
int err;
- err = remove_suid(out->f_path.dentry);
+ err = remove_suid(&out->f_path);
if (unlikely(err))
return err;
@@ -835,7 +835,7 @@ generic_file_splice_write(struct pipe_in
if (killpriv)
err = security_inode_killpriv(out->f_path.dentry);
if (!err && killsuid)
- err = __remove_suid(out->f_path.dentry, killsuid);
+ err = __remove_suid(&out->f_path, killsuid);
mutex_unlock(&inode->i_mutex);
if (err)
return err;
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -727,7 +727,7 @@ start:
!capable(CAP_FSETID)) {
error = xfs_write_clear_setuid(xip);
if (likely(!error))
- error = -remove_suid(file->f_path.dentry);
+ error = -remove_suid(&file->f_path);
if (unlikely(error)) {
goto out_unlock_internal;
}
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1766,9 +1766,9 @@ extern void __iget(struct inode * inode)
extern void clear_inode(struct inode *);
extern void destroy_inode(struct inode *);
extern struct inode *new_inode(struct super_block *);
-extern int __remove_suid(struct dentry *, int);
+extern int __remove_suid(struct path *, int);
extern int should_remove_suid(struct dentry *);
-extern int remove_suid(struct dentry *);
+extern int remove_suid(struct path *);
extern void __insert_inode_hash(struct inode *, unsigned long hashval);
extern void remove_inode_hash(struct inode *);
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1610,26 +1610,26 @@ int should_remove_suid(struct dentry *de
}
EXPORT_SYMBOL(should_remove_suid);
-int __remove_suid(struct dentry *dentry, int kill)
+int __remove_suid(struct path *path, int kill)
{
struct iattr newattrs;
newattrs.ia_valid = ATTR_FORCE | kill;
- return notify_change(dentry, &newattrs);
+ return notify_change(path->dentry, &newattrs);
}
-int remove_suid(struct dentry *dentry)
+int remove_suid(struct path *path)
{
- int killsuid = should_remove_suid(dentry);
- int killpriv = security_inode_need_killpriv(dentry);
+ int killsuid = should_remove_suid(path->dentry);
+ int killpriv = security_inode_need_killpriv(path->dentry);
int error = 0;
if (killpriv < 0)
return killpriv;
if (killpriv)
- error = security_inode_killpriv(dentry);
+ error = security_inode_killpriv(path->dentry);
if (!error && killsuid)
- error = __remove_suid(dentry, killsuid);
+ error = __remove_suid(path, killsuid);
return error;
}
@@ -2342,7 +2342,7 @@ __generic_file_aio_write_nolock(struct k
if (count == 0)
goto out;
- err = remove_suid(file->f_path.dentry);
+ err = remove_suid(&file->f_path);
if (err)
goto out;
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -378,7 +378,7 @@ xip_file_write(struct file *filp, const
if (count == 0)
goto out_backing;
- ret = remove_suid(filp->f_path.dentry);
+ ret = remove_suid(&filp->f_path);
if (ret)
goto out_backing;
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1525,7 +1525,7 @@ shmem_file_write(struct file *file, cons
if (err || !count)
goto out;
- err = remove_suid(file->f_path.dentry);
+ err = remove_suid(&file->f_path);
if (err)
goto out;

View File

@@ -1,107 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_create LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 2 +-
include/linux/security.h | 9 ++++++---
security/dummy.c | 2 +-
security/security.c | 5 +++--
security/selinux/hooks.c | 3 ++-
5 files changed, 13 insertions(+), 8 deletions(-)
--- a/fs/namei.c 2007-11-02 17:44:43.000000000 -0400
+++ b/fs/namei.c 2007-11-02 17:49:23.000000000 -0400
@@ -1583,7 +1583,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 2007-11-02 17:44:43.000000000 -0400
+++ b/include/linux/security.h 2007-11-02 17:49:39.000000000 -0400
@@ -297,6 +297,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:
@@ -1247,8 +1248,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);
@@ -1503,7 +1504,8 @@ int security_inode_alloc(struct inode *i
void security_inode_free(struct inode *inode);
int security_inode_init_security(struct inode *inode, struct inode *dir,
char **name, void **value, size_t *len);
-int security_inode_create(struct inode *dir, struct dentry *dentry, int mode);
+int security_inode_create(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt, int mode);
int security_inode_link(struct dentry *old_dentry, struct inode *dir,
struct dentry *new_dentry);
int security_inode_unlink(struct inode *dir, struct dentry *dentry);
@@ -1813,6 +1815,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 2007-11-02 17:44:43.000000000 -0400
+++ b/security/dummy.c 2007-11-02 17:49:23.000000000 -0400
@@ -262,7 +262,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/security.c 2007-11-02 17:46:44.000000000 -0400
+++ b/security/security.c 2007-11-02 17:49:23.000000000 -0400
@@ -329,11 +329,12 @@ int security_inode_init_security(struct
}
EXPORT_SYMBOL(security_inode_init_security);
-int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
+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);
}
int security_inode_link(struct dentry *old_dentry, struct inode *dir,
--- a/security/selinux/hooks.c 2007-11-02 17:44:43.000000000 -0400
+++ b/security/selinux/hooks.c 2007-11-02 17:49:23.000000000 -0400
@@ -2184,7 +2184,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);
}

View File

@@ -1,110 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_getxattr LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/xattr.c | 2 +-
include/linux/security.h | 11 +++++++----
security/dummy.c | 3 ++-
security/security.c | 5 +++--
security/selinux/hooks.c | 3 ++-
5 files changed, 15 insertions(+), 9 deletions(-)
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -115,7 +115,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
@@ -405,7 +405,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
@@ -1291,7 +1291,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);
int (*inode_need_killpriv) (struct dentry *dentry);
@@ -1554,7 +1555,8 @@ int security_inode_setxattr(struct dentr
void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
char *name, void *value, size_t size,
int flags);
-int security_inode_getxattr(struct dentry *dentry, char *name);
+int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name);
int security_inode_listxattr(struct dentry *dentry);
int security_inode_removexattr(struct dentry *dentry, char *name);
int security_inode_need_killpriv(struct dentry *dentry);
@@ -1954,7 +1956,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
@@ -365,7 +365,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/security.c
+++ b/security/security.c
@@ -458,11 +458,12 @@ void security_inode_post_setxattr(struct
security_ops->inode_post_setxattr(dentry, mnt, name, value, size, flags);
}
-int security_inode_getxattr(struct dentry *dentry, char *name)
+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);
}
int security_inode_listxattr(struct dentry *dentry)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2409,7 +2409,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);
}

View File

@@ -1,134 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: 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 <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 3 ++-
include/linux/security.h | 16 +++++++++++-----
security/dummy.c | 6 ++++--
security/security.c | 8 +++++---
security/selinux/hooks.c | 9 +++++++--
5 files changed, 29 insertions(+), 13 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2356,7 +2356,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
@@ -303,8 +303,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.
@@ -1255,8 +1257,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);
@@ -1513,8 +1516,9 @@ int security_inode_init_security(struct
char **name, void **value, size_t *len);
int security_inode_create(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode);
-int security_inode_link(struct dentry *old_dentry, struct inode *dir,
- struct dentry *new_dentry);
+int security_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
+ struct inode *dir, struct dentry *new_dentry,
+ struct vfsmount *new_mnt);
int security_inode_unlink(struct inode *dir, struct dentry *dentry);
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, const char *old_name);
@@ -1832,8 +1836,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
@@ -267,8 +267,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/security.c
+++ b/security/security.c
@@ -336,12 +336,14 @@ int security_inode_create(struct inode *
return security_ops->inode_create(dir, dentry, mnt, mode);
}
-int security_inode_link(struct dentry *old_dentry, struct inode *dir,
- struct dentry *new_dentry)
+int security_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
+ struct inode *dir, 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);
}
int security_inode_unlink(struct inode *dir, struct dentry *dentry)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2190,11 +2190,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)
return rc;
return may_link(dir, old_dentry, MAY_LINK);

View File

@@ -1,105 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_listxattr LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/xattr.c | 2 +-
include/linux/security.h | 9 +++++----
security/dummy.c | 2 +-
security/security.c | 4 ++--
security/selinux/hooks.c | 2 +-
5 files changed, 10 insertions(+), 9 deletions(-)
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -148,7 +148,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
@@ -409,7 +409,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
@@ -1293,7 +1293,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);
int (*inode_need_killpriv) (struct dentry *dentry);
int (*inode_killpriv) (struct dentry *dentry);
@@ -1557,7 +1557,7 @@ void security_inode_post_setxattr(struct
int flags);
int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
char *name);
-int security_inode_listxattr(struct dentry *dentry);
+int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt);
int security_inode_removexattr(struct dentry *dentry, char *name);
int security_inode_need_killpriv(struct dentry *dentry);
int security_inode_killpriv(struct dentry *dentry);
@@ -1962,7 +1962,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
@@ -371,7 +371,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/security.c
+++ b/security/security.c
@@ -466,11 +466,11 @@ int security_inode_getxattr(struct dentr
return security_ops->inode_getxattr(dentry, mnt, name);
}
-int security_inode_listxattr(struct dentry *dentry)
+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);
}
int security_inode_removexattr(struct dentry *dentry, char *name)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2415,7 +2415,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);
}

View File

@@ -1,106 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_mkdir LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 2 +-
include/linux/security.h | 8 ++++++--
security/dummy.c | 2 +-
security/security.c | 5 +++--
security/selinux/hooks.c | 3 ++-
5 files changed, 13 insertions(+), 7 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2009,7 +2009,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
@@ -322,6 +322,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:
@@ -1256,7 +1257,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);
@@ -1513,7 +1515,8 @@ int security_inode_link(struct dentry *o
int security_inode_unlink(struct inode *dir, struct dentry *dentry);
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
const char *old_name);
-int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode);
+int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt, int mode);
int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
@@ -1846,6 +1849,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
@@ -285,7 +285,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/security.c
+++ b/security/security.c
@@ -359,11 +359,12 @@ int security_inode_symlink(struct inode
return security_ops->inode_symlink(dir, dentry, old_name);
}
-int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+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);
}
int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2215,7 +2215,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);
}

View File

@@ -1,110 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_mknod LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 2 +-
include/linux/security.h | 7 +++++--
security/dummy.c | 2 +-
security/security.c | 5 +++--
security/selinux/hooks.c | 5 +++--
5 files changed, 13 insertions(+), 8 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1932,7 +1932,7 @@ int vfs_mknod(struct inode *dir, struct
if (!dir->i_op || !dir->i_op->mknod)
return -EPERM;
- error = security_inode_mknod(dir, dentry, mode, dev);
+ error = security_inode_mknod(dir, dentry, mnt, mode, dev);
if (error)
return error;
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -337,6 +337,7 @@ struct request_sock;
* and not this hook.
* @dir contains the inode structure of parent of the new file.
* @dentry contains the dentry structure of the new file.
+ * @mnt is the vfsmount corresponding to @dentry (may be NULL).
* @mode contains the mode of the new file.
* @dev contains the device number.
* Return 0 if permission is granted.
@@ -1261,7 +1262,7 @@ struct security_operations {
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);
+ 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);
@@ -1518,7 +1519,8 @@ int security_inode_symlink(struct inode
int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode);
int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
-int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
+int security_inode_mknod(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt, int mode, dev_t dev);
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry);
int security_inode_readlink(struct dentry *dentry);
@@ -1863,6 +1865,7 @@ static inline int security_inode_rmdir (
static inline int security_inode_mknod (struct inode *dir,
struct dentry *dentry,
+ struct vfsmount *mnt,
int mode, dev_t dev)
{
return 0;
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -296,7 +296,7 @@ static int dummy_inode_rmdir (struct ino
}
static int dummy_inode_mknod (struct inode *inode, struct dentry *dentry,
- int mode, dev_t dev)
+ struct vfsmount *mnt, int mode, dev_t dev)
{
return 0;
}
--- a/security/security.c
+++ b/security/security.c
@@ -374,11 +374,12 @@ int security_inode_rmdir(struct inode *d
return security_ops->inode_rmdir(dir, dentry);
}
-int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+int security_inode_mknod(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt, int mode, dev_t dev)
{
if (unlikely(IS_PRIVATE(dir)))
return 0;
- return security_ops->inode_mknod(dir, dentry, mode, dev);
+ return security_ops->inode_mknod(dir, dentry, mnt, mode, dev);
}
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2226,11 +2226,12 @@ static int selinux_inode_rmdir(struct in
return may_link(dir, dentry, MAY_RMDIR);
}
-static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt, int mode, dev_t dev)
{
int rc;
- rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
+ rc = secondary_ops->inode_mknod(dir, dentry, mnt, mode, dev);
if (rc)
return rc;

View File

@@ -1,104 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_readlink LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/stat.c | 2 +-
include/linux/security.h | 8 +++++---
security/dummy.c | 2 +-
security/security.c | 4 ++--
security/selinux/hooks.c | 2 +-
5 files changed, 10 insertions(+), 8 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
@@ -352,6 +352,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.
@@ -1266,7 +1267,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,
@@ -1524,7 +1525,7 @@ int security_inode_mknod(struct inode *d
struct vfsmount *mnt, int mode, dev_t dev);
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry);
-int security_inode_readlink(struct dentry *dentry);
+int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt);
int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
int security_inode_permission(struct inode *inode, int mask, struct nameidata *nd);
int security_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
@@ -1881,7 +1882,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
@@ -309,7 +309,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/security.c
+++ b/security/security.c
@@ -392,11 +392,11 @@ int security_inode_rename(struct inode *
new_dir, new_dentry);
}
-int security_inode_readlink(struct dentry *dentry)
+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);
}
int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2245,7 +2245,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);
}

View File

@@ -1,126 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_removexattr LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/xattr.c | 2 +-
include/linux/security.h | 13 ++++++++-----
security/commoncap.c | 3 ++-
security/dummy.c | 3 ++-
security/security.c | 5 +++--
security/selinux/hooks.c | 3 ++-
6 files changed, 18 insertions(+), 11 deletions(-)
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -176,7 +176,7 @@ vfs_removexattr(struct dentry *dentry, s
if (error)
return error;
- error = security_inode_removexattr(dentry, name);
+ error = security_inode_removexattr(dentry, mnt, name);
if (error)
return error;
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -57,7 +57,7 @@ extern int cap_bprm_set_security (struct
extern void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe);
extern int cap_bprm_secureexec(struct linux_binprm *bprm);
extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, void *value, size_t size, int flags);
-extern int cap_inode_removexattr(struct dentry *dentry, char *name);
+extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name);
extern int cap_inode_need_killpriv(struct dentry *dentry);
extern int cap_inode_killpriv(struct dentry *dentry);
extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
@@ -1294,7 +1294,8 @@ struct security_operations {
int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
char *name);
int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt);
- int (*inode_removexattr) (struct dentry *dentry, char *name);
+ int (*inode_removexattr) (struct dentry *dentry, struct vfsmount *mnt,
+ char *name);
int (*inode_need_killpriv) (struct dentry *dentry);
int (*inode_killpriv) (struct dentry *dentry);
int (*inode_getsecurity)(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
@@ -1558,7 +1559,8 @@ void security_inode_post_setxattr(struct
int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
char *name);
int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt);
-int security_inode_removexattr(struct dentry *dentry, char *name);
+int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name);
int security_inode_need_killpriv(struct dentry *dentry);
int security_inode_killpriv(struct dentry *dentry);
int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
@@ -1968,9 +1970,10 @@ static inline int security_inode_listxat
return 0;
}
-static inline int security_inode_removexattr (struct dentry *dentry, char *name)
+static inline int security_inode_removexattr (struct dentry *dentry,
+ struct vfsmount *mnt, char *name)
{
- return cap_inode_removexattr(dentry, name);
+ return cap_inode_removexattr(dentry, mnt, name);
}
static inline int security_inode_need_killpriv(struct dentry *dentry)
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -382,7 +382,8 @@ int cap_inode_setxattr(struct dentry *de
return 0;
}
-int cap_inode_removexattr(struct dentry *dentry, char *name)
+int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name)
{
if (!strcmp(name, XATTR_NAME_CAPS)) {
if (!capable(CAP_SETFCAP))
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -376,7 +376,8 @@ static int dummy_inode_listxattr (struct
return 0;
}
-static int dummy_inode_removexattr (struct dentry *dentry, char *name)
+static int dummy_inode_removexattr (struct dentry *dentry, struct vfsmount *mnt,
+ char *name)
{
if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof(XATTR_SECURITY_PREFIX) - 1) &&
--- a/security/security.c
+++ b/security/security.c
@@ -473,11 +473,12 @@ int security_inode_listxattr(struct dent
return security_ops->inode_listxattr(dentry, mnt);
}
-int security_inode_removexattr(struct dentry *dentry, char *name)
+int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- return security_ops->inode_removexattr(dentry, name);
+ return security_ops->inode_removexattr(dentry, mnt, name);
}
int security_inode_need_killpriv(struct dentry *dentry)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2420,7 +2420,8 @@ static int selinux_inode_listxattr (stru
return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
}
-static int selinux_inode_removexattr (struct dentry *dentry, char *name)
+static int selinux_inode_removexattr (struct dentry *dentry,
+ struct vfsmount *mnt, char *name)
{
if (strcmp(name, XATTR_NAME_SELINUX))
return selinux_inode_setotherxattr(dentry, name);

View File

@@ -1,136 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_rename LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 6 ++++--
include/linux/security.h | 13 ++++++++++---
security/dummy.c | 4 +++-
security/security.c | 7 ++++---
security/selinux/hooks.c | 8 ++++++--
5 files changed, 27 insertions(+), 11 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2480,7 +2480,8 @@ static int vfs_rename_dir(struct inode *
return error;
}
- error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry);
+ error = security_inode_rename(old_dir, old_dentry, old_mnt,
+ new_dir, new_dentry, new_mnt);
if (error)
return error;
@@ -2514,7 +2515,8 @@ static int vfs_rename_other(struct inode
struct inode *target;
int error;
- error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry);
+ error = security_inode_rename(old_dir, old_dentry, old_mnt,
+ new_dir, new_dentry, new_mnt);
if (error)
return error;
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -350,8 +350,10 @@ struct request_sock;
* Check for permission to rename a file or directory.
* @old_dir contains the inode structure for parent of the old link.
* @old_dentry contains the dentry structure of the old link.
+ * @old_mnt is the vfsmount corresponding to @old_dentry (may be NULL).
* @new_dir contains the inode structure for parent of the new link.
* @new_dentry contains the dentry structure of the new link.
+ * @new_mnt is the vfsmount corresponding to @new_dentry (may be NULL).
* Return 0 if permission is granted.
* @inode_readlink:
* Check the permission to read the symbolic link.
@@ -1273,7 +1275,9 @@ struct security_operations {
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,
- struct inode *new_dir, struct dentry *new_dentry);
+ struct vfsmount *old_mnt,
+ struct inode *new_dir, struct dentry *new_dentry,
+ struct vfsmount *new_mnt);
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);
@@ -1534,7 +1538,8 @@ int security_inode_rmdir(struct inode *d
int security_inode_mknod(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode, dev_t dev);
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry);
+ struct vfsmount *old_mnt, struct inode *new_dir,
+ struct dentry *new_dentry, struct vfsmount *new_mnt);
int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt);
int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
int security_inode_permission(struct inode *inode, int mask, struct nameidata *nd);
@@ -1890,8 +1895,10 @@ static inline int security_inode_mknod (
static inline int security_inode_rename (struct inode *old_dir,
struct dentry *old_dentry,
+ struct vfsmount *old_mnt,
struct inode *new_dir,
- struct dentry *new_dentry)
+ struct dentry *new_dentry,
+ struct vfsmount *new_mnt)
{
return 0;
}
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -307,8 +307,10 @@ static int dummy_inode_mknod (struct ino
static int dummy_inode_rename (struct inode *old_inode,
struct dentry *old_dentry,
+ struct vfsmount *old_mnt,
struct inode *new_inode,
- struct dentry *new_dentry)
+ struct dentry *new_dentry,
+ struct vfsmount *new_mnt)
{
return 0;
}
--- a/security/security.c
+++ b/security/security.c
@@ -387,13 +387,14 @@ int security_inode_mknod(struct inode *d
}
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
+ struct vfsmount *old_mnt, struct inode *new_dir,
+ struct dentry *new_dentry, struct vfsmount *new_mnt)
{
if (unlikely(IS_PRIVATE(old_dentry->d_inode) ||
(new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode))))
return 0;
- return security_ops->inode_rename(old_dir, old_dentry,
- new_dir, new_dentry);
+ return security_ops->inode_rename(old_dir, old_dentry, old_mnt,
+ new_dir, new_dentry, new_mnt);
}
int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2246,8 +2246,12 @@ static int selinux_inode_mknod(struct in
return may_create(dir, dentry, inode_mode_to_security_class(mode));
}
-static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
- struct inode *new_inode, struct dentry *new_dentry)
+static int selinux_inode_rename(struct inode *old_inode,
+ struct dentry *old_dentry,
+ struct vfsmount *old_mnt,
+ struct inode *new_inode,
+ struct dentry *new_dentry,
+ struct vfsmount *new_mnt)
{
return may_rename(old_inode, old_dentry, new_inode, new_dentry);
}

View File

@@ -1,109 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_rmdir LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 2 +-
include/linux/security.h | 10 +++++++---
security/dummy.c | 3 ++-
security/security.c | 5 +++--
security/selinux/hooks.c | 3 ++-
5 files changed, 15 insertions(+), 8 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2104,7 +2104,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
@@ -332,6 +332,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
@@ -1265,7 +1266,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,
@@ -1524,7 +1526,8 @@ int security_inode_symlink(struct inode
struct vfsmount *mnt, const char *old_name);
int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode);
-int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
+int security_inode_rmdir(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt);
int security_inode_mknod(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode, dev_t dev);
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
@@ -1867,7 +1870,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
@@ -292,7 +292,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/security.c
+++ b/security/security.c
@@ -369,11 +369,12 @@ int security_inode_mkdir(struct inode *d
return security_ops->inode_mkdir(dir, dentry, mnt, mode);
}
-int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
+int security_inode_rmdir(struct inode *dir, 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);
}
int security_inode_mknod(struct inode *dir, struct dentry *dentry,
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2227,7 +2227,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);
}

View File

@@ -1,119 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_setattr LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/attr.c | 4 ++--
include/linux/security.h | 8 ++++++--
security/dummy.c | 3 ++-
security/security.c | 5 +++--
security/selinux/hooks.c | 5 +++--
5 files changed, 16 insertions(+), 9 deletions(-)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -159,13 +159,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
@@ -372,6 +372,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:
@@ -1264,7 +1265,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,
@@ -1519,7 +1521,8 @@ int security_inode_rename(struct inode *
int security_inode_readlink(struct dentry *dentry);
int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
int security_inode_permission(struct inode *inode, int mask, struct nameidata *nd);
-int security_inode_setattr(struct dentry *dentry, struct iattr *attr);
+int security_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
+ struct iattr *attr);
int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
void security_inode_delete(struct inode *inode);
int security_inode_setxattr(struct dentry *dentry, char *name,
@@ -1887,6 +1890,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
@@ -325,7 +325,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/security.c
+++ b/security/security.c
@@ -411,11 +411,12 @@ int security_inode_permission(struct ino
return security_ops->inode_permission(inode, mask, nd);
}
-int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
+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);
}
int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2275,11 +2275,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;

View File

@@ -1,210 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_setxattr LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/xattr.c | 4 ++--
include/linux/security.h | 35 +++++++++++++++++++++--------------
security/commoncap.c | 4 ++--
security/dummy.c | 9 ++++++---
security/security.c | 14 ++++++++------
security/selinux/hooks.c | 8 ++++++--
6 files changed, 45 insertions(+), 29 deletions(-)
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -79,7 +79,7 @@ vfs_setxattr(struct dentry *dentry, stru
return error;
mutex_lock(&inode->i_mutex);
- error = security_inode_setxattr(dentry, name, value, size, flags);
+ error = security_inode_setxattr(dentry, mnt, name, value, size, flags);
if (error)
goto out;
error = -EOPNOTSUPP;
@@ -87,7 +87,7 @@ vfs_setxattr(struct dentry *dentry, stru
error = inode->i_op->setxattr(dentry, name, value, size, flags);
if (!error) {
fsnotify_xattr(dentry);
- security_inode_post_setxattr(dentry, name, value,
+ security_inode_post_setxattr(dentry, mnt, name, value,
size, flags);
}
} else if (!strncmp(name, XATTR_SECURITY_PREFIX,
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -56,7 +56,7 @@ extern void cap_capset_set (struct task_
extern int cap_bprm_set_security (struct linux_binprm *bprm);
extern void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe);
extern int cap_bprm_secureexec(struct linux_binprm *bprm);
-extern int cap_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags);
+extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, void *value, size_t size, int flags);
extern int cap_inode_removexattr(struct dentry *dentry, char *name);
extern int cap_inode_need_killpriv(struct dentry *dentry);
extern int cap_inode_killpriv(struct dentry *dentry);
@@ -398,11 +398,11 @@ struct request_sock;
* inode.
* @inode_setxattr:
* Check permission before setting the extended attributes
- * @value identified by @name for @dentry.
+ * @value identified by @name for @dentry and @mnt.
* Return 0 if permission is granted.
* @inode_post_setxattr:
* Update inode security field after successful setxattr operation.
- * @value identified by @name for @dentry.
+ * @value identified by @name for @dentry and @mnt.
* @inode_getxattr:
* Check permission before obtaining the extended attributes
* identified by @name for @dentry.
@@ -1285,9 +1285,11 @@ struct security_operations {
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,
- size_t size, int flags);
- void (*inode_post_setxattr) (struct dentry *dentry, char *name, void *value,
+ int (*inode_setxattr) (struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size, int flags);
+ void (*inode_post_setxattr) (struct dentry *dentry,
+ struct vfsmount *mnt,
+ char *name, void *value,
size_t size, int flags);
int (*inode_getxattr) (struct dentry *dentry, char *name);
int (*inode_listxattr) (struct dentry *dentry);
@@ -1547,10 +1549,11 @@ int security_inode_setattr(struct dentry
struct iattr *attr);
int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
void security_inode_delete(struct inode *inode);
-int security_inode_setxattr(struct dentry *dentry, char *name,
- void *value, size_t size, int flags);
-void security_inode_post_setxattr(struct dentry *dentry, char *name,
- void *value, size_t size, int flags);
+int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size, int flags);
+void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size,
+ int flags);
int security_inode_getxattr(struct dentry *dentry, char *name);
int security_inode_listxattr(struct dentry *dentry);
int security_inode_removexattr(struct dentry *dentry, char *name);
@@ -1937,14 +1940,18 @@ static inline int security_inode_getattr
static inline void security_inode_delete (struct inode *inode)
{ }
-static inline int security_inode_setxattr (struct dentry *dentry, char *name,
+static inline int security_inode_setxattr (struct dentry *dentry,
+ struct vfsmount *mnt, char *name,
void *value, size_t size, int flags)
{
- return cap_inode_setxattr(dentry, name, value, size, flags);
+ return cap_inode_setxattr(dentry, mnt, name, value, size, flags);
}
-static inline void security_inode_post_setxattr (struct dentry *dentry, char *name,
- void *value, size_t size, int flags)
+static inline void security_inode_post_setxattr (struct dentry *dentry,
+ struct vfsmount *mnt,
+ char *name,
+ void *value, size_t size,
+ int flags)
{ }
static inline int security_inode_getxattr (struct dentry *dentry, char *name)
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -368,8 +368,8 @@ int cap_bprm_secureexec (struct linux_bi
current->egid != current->gid);
}
-int cap_inode_setxattr(struct dentry *dentry, char *name, void *value,
- size_t size, int flags)
+int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
+ void *value, size_t size, int flags)
{
if (!strcmp(name, XATTR_NAME_CAPS)) {
if (!capable(CAP_SETFCAP))
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -347,8 +347,9 @@ static void dummy_inode_delete (struct i
return;
}
-static int dummy_inode_setxattr (struct dentry *dentry, char *name, void *value,
- size_t size, int flags)
+static int dummy_inode_setxattr (struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size,
+ int flags)
{
if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof(XATTR_SECURITY_PREFIX) - 1) &&
@@ -357,7 +358,9 @@ static int dummy_inode_setxattr (struct
return 0;
}
-static void dummy_inode_post_setxattr (struct dentry *dentry, char *name, void *value,
+static void dummy_inode_post_setxattr (struct dentry *dentry,
+ struct vfsmount *mnt,
+ char *name, void *value,
size_t size, int flags)
{
}
--- a/security/security.c
+++ b/security/security.c
@@ -440,20 +440,22 @@ void security_inode_delete(struct inode
security_ops->inode_delete(inode);
}
-int security_inode_setxattr(struct dentry *dentry, char *name,
- void *value, size_t size, int flags)
+int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size, int flags)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- return security_ops->inode_setxattr(dentry, name, value, size, flags);
+ return security_ops->inode_setxattr(dentry, mnt, name, value, size,
+ flags);
}
-void security_inode_post_setxattr(struct dentry *dentry, char *name,
- void *value, size_t size, int flags)
+void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size,
+ int flags)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return;
- security_ops->inode_post_setxattr(dentry, name, value, size, flags);
+ security_ops->inode_post_setxattr(dentry, mnt, name, value, size, flags);
}
int security_inode_getxattr(struct dentry *dentry, char *name)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2332,7 +2332,9 @@ static int selinux_inode_setotherxattr(s
return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
}
-static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
+static int selinux_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size,
+ int flags)
{
struct task_security_struct *tsec = current->security;
struct inode *inode = dentry->d_inode;
@@ -2381,7 +2383,9 @@ static int selinux_inode_setxattr(struct
&ad);
}
-static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
+static void selinux_inode_post_setxattr(struct dentry *dentry,
+ struct vfsmount *mnt,
+ char *name,
void *value, size_t size, int flags)
{
struct inode *inode = dentry->d_inode;

View File

@@ -1,105 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_symlink LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 2 +-
include/linux/security.h | 8 +++++---
security/dummy.c | 2 +-
security/security.c | 4 ++--
security/selinux/hooks.c | 3 ++-
5 files changed, 11 insertions(+), 8 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2277,7 +2277,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
@@ -315,6 +315,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:
@@ -1256,8 +1257,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);
@@ -1515,7 +1516,7 @@ int security_inode_link(struct dentry *o
struct dentry *new_dentry);
int security_inode_unlink(struct inode *dir, struct dentry *dentry);
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
- const char *old_name);
+ struct vfsmount *mnt, const char *old_name);
int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode);
int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
@@ -1844,6 +1845,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
@@ -279,7 +279,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/security.c
+++ b/security/security.c
@@ -352,11 +352,11 @@ int security_inode_unlink(struct inode *
}
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
- const char *old_name)
+ 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);
}
int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2210,7 +2210,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);
}

View File

@@ -1,114 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_unlink LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 2 +-
include/linux/security.h | 10 +++++++---
security/dummy.c | 3 ++-
security/security.c | 5 +++--
security/selinux/hooks.c | 5 +++--
5 files changed, 16 insertions(+), 9 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2184,7 +2184,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
@@ -312,6 +312,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.
@@ -1261,7 +1262,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,
@@ -1521,7 +1523,8 @@ int security_inode_create(struct inode *
int security_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
struct inode *dir, struct dentry *new_dentry,
struct vfsmount *new_mnt);
-int security_inode_unlink(struct inode *dir, struct dentry *dentry);
+int security_inode_unlink(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt);
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, const char *old_name);
int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
@@ -1848,7 +1851,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
@@ -275,7 +275,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/security.c
+++ b/security/security.c
@@ -346,11 +346,12 @@ int security_inode_link(struct dentry *o
new_dentry, new_mnt);
}
-int security_inode_unlink(struct inode *dir, struct dentry *dentry)
+int security_inode_unlink(struct inode *dir, 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);
}
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2205,11 +2205,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);

View File

@@ -1,540 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: 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 <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/xattr.c | 58 ++++++++++++++++++++++++-----------------------
include/linux/security.h | 40 +++++++++++++++++++-------------
include/linux/xattr.h | 8 +++---
security/commoncap.c | 4 +--
security/dummy.c | 10 ++++----
security/security.c | 21 +++++++++--------
security/selinux/hooks.c | 10 ++++----
7 files changed, 84 insertions(+), 67 deletions(-)
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -69,7 +69,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;
@@ -79,7 +79,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;
@@ -106,7 +106,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;
@@ -115,7 +115,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;
@@ -143,12 +143,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;
@@ -164,7 +164,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;
@@ -176,7 +177,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;
@@ -196,7 +197,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;
@@ -223,7 +224,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;
}
@@ -238,7 +239,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;
}
@@ -253,7 +254,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;
}
@@ -271,7 +272,7 @@ sys_fsetxattr(int fd, char __user *name,
return error;
dentry = f->f_path.dentry;
audit_inode(NULL, dentry);
- 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;
}
@@ -281,7 +282,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 size)
+ void __user *value, size_t size, struct file *file)
{
ssize_t error;
void *kvalue = NULL;
@@ -301,7 +302,7 @@ getxattr(struct dentry *dentry, struct v
return -ENOMEM;
}
- error = vfs_getxattr(dentry, mnt, kname, kvalue, size);
+ error = vfs_getxattr(dentry, mnt, kname, kvalue, size, file);
if (error > 0) {
if (size && copy_to_user(value, kvalue, error))
error = -EFAULT;
@@ -324,7 +325,7 @@ sys_getxattr(char __user *path, char __u
error = user_path_walk(path, &nd);
if (error)
return error;
- error = getxattr(nd.dentry, nd.mnt, name, value, size);
+ error = getxattr(nd.dentry, nd.mnt, name, value, size, NULL);
path_release(&nd);
return error;
}
@@ -339,7 +340,7 @@ sys_lgetxattr(char __user *path, char __
error = user_path_walk_link(path, &nd);
if (error)
return error;
- error = getxattr(nd.dentry, nd.mnt, name, value, size);
+ error = getxattr(nd.dentry, nd.mnt, name, value, size, NULL);
path_release(&nd);
return error;
}
@@ -354,7 +355,7 @@ sys_fgetxattr(int fd, char __user *name,
if (!f)
return error;
audit_inode(NULL, f->f_path.dentry);
- error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size);
+ error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size, f);
fput(f);
return error;
}
@@ -364,7 +365,7 @@ sys_fgetxattr(int fd, char __user *name,
*/
static ssize_t
listxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *list,
- size_t size)
+ size_t size, struct file *file)
{
ssize_t error;
char *klist = NULL;
@@ -377,7 +378,7 @@ listxattr(struct dentry *dentry, struct
return -ENOMEM;
}
- error = vfs_listxattr(dentry, mnt, klist, size);
+ error = vfs_listxattr(dentry, mnt, klist, size, file);
if (error > 0) {
if (size && copy_to_user(list, klist, error))
error = -EFAULT;
@@ -399,7 +400,7 @@ sys_listxattr(char __user *path, char __
error = user_path_walk(path, &nd);
if (error)
return error;
- error = listxattr(nd.dentry, nd.mnt, list, size);
+ error = listxattr(nd.dentry, nd.mnt, list, size, NULL);
path_release(&nd);
return error;
}
@@ -413,7 +414,7 @@ sys_llistxattr(char __user *path, char _
error = user_path_walk_link(path, &nd);
if (error)
return error;
- error = listxattr(nd.dentry, nd.mnt, list, size);
+ error = listxattr(nd.dentry, nd.mnt, list, size, NULL);
path_release(&nd);
return error;
}
@@ -428,7 +429,7 @@ sys_flistxattr(int fd, char __user *list
if (!f)
return error;
audit_inode(NULL, f->f_path.dentry);
- error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size);
+ error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size, f);
fput(f);
return error;
}
@@ -437,7 +438,8 @@ sys_flistxattr(int fd, char __user *list
* Extended attribute REMOVE operations
*/
static long
-removexattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name)
+removexattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name,
+ struct file *file)
{
int error;
char kname[XATTR_NAME_MAX + 1];
@@ -448,7 +450,7 @@ removexattr(struct dentry *dentry, struc
if (error < 0)
return error;
- return vfs_removexattr(dentry, mnt, kname);
+ return vfs_removexattr(dentry, mnt, kname, file);
}
asmlinkage long
@@ -460,7 +462,7 @@ sys_removexattr(char __user *path, char
error = user_path_walk(path, &nd);
if (error)
return error;
- error = removexattr(nd.dentry, nd.mnt, name);
+ error = removexattr(nd.dentry, nd.mnt, name, NULL);
path_release(&nd);
return error;
}
@@ -474,7 +476,7 @@ sys_lremovexattr(char __user *path, char
error = user_path_walk_link(path, &nd);
if (error)
return error;
- error = removexattr(nd.dentry, nd.mnt, name);
+ error = removexattr(nd.dentry, nd.mnt, name, NULL);
path_release(&nd);
return error;
}
@@ -491,7 +493,7 @@ sys_fremovexattr(int fd, char __user *na
return error;
dentry = f->f_path.dentry;
audit_inode(NULL, dentry);
- error = removexattr(dentry, f->f_path.mnt, name);
+ error = removexattr(dentry, f->f_path.mnt, name, f);
fput(f);
return error;
}
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -56,8 +56,8 @@ extern void cap_capset_set (struct task_
extern int cap_bprm_set_security (struct linux_binprm *bprm);
extern void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe);
extern int cap_bprm_secureexec(struct linux_binprm *bprm);
-extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, void *value, size_t size, int flags);
-extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name);
+extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, void *value, size_t size, int flags, struct file *file);
+extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name, struct file *file);
extern int cap_inode_need_killpriv(struct dentry *dentry);
extern int cap_inode_killpriv(struct dentry *dentry);
extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
@@ -1286,16 +1286,18 @@ struct security_operations {
int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
void (*inode_delete) (struct inode *inode);
int (*inode_setxattr) (struct dentry *dentry, struct vfsmount *mnt,
- char *name, void *value, size_t size, int flags);
+ char *name, void *value, size_t size, int flags,
+ struct file *file);
void (*inode_post_setxattr) (struct dentry *dentry,
struct vfsmount *mnt,
char *name, void *value,
size_t size, int flags);
int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
- char *name);
- int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt);
+ char *name, struct file *file);
+ int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt,
+ struct file *file);
int (*inode_removexattr) (struct dentry *dentry, struct vfsmount *mnt,
- char *name);
+ char *name, struct file *file);
int (*inode_need_killpriv) (struct dentry *dentry);
int (*inode_killpriv) (struct dentry *dentry);
int (*inode_getsecurity)(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
@@ -1552,15 +1554,17 @@ int security_inode_setattr(struct dentry
int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
void security_inode_delete(struct inode *inode);
int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name, void *value, size_t size, int flags);
+ char *name, void *value, size_t size, int flags,
+ struct file *file);
void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
char *name, void *value, size_t size,
int flags);
int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name);
-int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt);
+ char *name, struct file *file);
+int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
+ struct file *file);
int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name);
+ char *name, struct file *file);
int security_inode_need_killpriv(struct dentry *dentry);
int security_inode_killpriv(struct dentry *dentry);
int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
@@ -1946,9 +1950,10 @@ static inline void security_inode_delete
static inline int security_inode_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)
{
- return cap_inode_setxattr(dentry, mnt, name, value, size, flags);
+ return cap_inode_setxattr(dentry, mnt, name, value, size, flags, file);
}
static inline void security_inode_post_setxattr (struct dentry *dentry,
@@ -1959,21 +1964,24 @@ static inline void security_inode_post_s
{ }
static inline int security_inode_getxattr (struct dentry *dentry,
- struct vfsmount *mnt, char *name)
+ struct vfsmount *mnt, char *name,
+ struct file *file)
{
return 0;
}
static inline int security_inode_listxattr (struct dentry *dentry,
- struct vfsmount *mnt)
+ struct vfsmount *mnt,
+ struct file *file)
{
return 0;
}
static inline int security_inode_removexattr (struct dentry *dentry,
- struct vfsmount *mnt, char *name)
+ struct vfsmount *mnt, char *name,
+ struct file *file)
{
- return cap_inode_removexattr(dentry, mnt, name);
+ return cap_inode_removexattr(dentry, mnt, name, file);
}
static inline int security_inode_need_killpriv(struct dentry *dentry)
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -47,12 +47,12 @@ struct xattr_handler {
};
ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, char *, void *,
- size_t);
+ size_t, struct file *);
ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list,
- size_t size);
+ size_t size, struct file *);
int vfs_setxattr(struct dentry *, struct vfsmount *, char *, void *, size_t,
- int);
-int vfs_removexattr(struct dentry *, struct vfsmount *, char *);
+ int, struct file *);
+int vfs_removexattr(struct dentry *, struct vfsmount *, char *, struct file *);
ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -369,7 +369,7 @@ int cap_bprm_secureexec (struct linux_bi
}
int cap_inode_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)
{
if (!strcmp(name, XATTR_NAME_CAPS)) {
if (!capable(CAP_SETFCAP))
@@ -383,7 +383,7 @@ int cap_inode_setxattr(struct dentry *de
}
int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name)
+ char *name, struct file *file)
{
if (!strcmp(name, XATTR_NAME_CAPS)) {
if (!capable(CAP_SETFCAP))
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -349,7 +349,7 @@ static void dummy_inode_delete (struct i
static int dummy_inode_setxattr (struct dentry *dentry, struct vfsmount *mnt,
char *name, void *value, size_t size,
- int flags)
+ int flags, struct file *file)
{
if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof(XATTR_SECURITY_PREFIX) - 1) &&
@@ -366,18 +366,20 @@ static void dummy_inode_post_setxattr (s
}
static int dummy_inode_getxattr (struct dentry *dentry,
- struct vfsmount *mnt, char *name)
+ struct vfsmount *mnt, char *name,
+ struct file *file)
{
return 0;
}
-static int dummy_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt)
+static int dummy_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt,
+ struct file *file)
{
return 0;
}
static int dummy_inode_removexattr (struct dentry *dentry, struct vfsmount *mnt,
- char *name)
+ char *name, struct file *file)
{
if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof(XATTR_SECURITY_PREFIX) - 1) &&
--- a/security/security.c
+++ b/security/security.c
@@ -441,12 +441,13 @@ void security_inode_delete(struct inode
}
int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name, void *value, size_t size, int flags)
+ char *name, void *value, size_t size, int flags,
+ struct file *file)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
return security_ops->inode_setxattr(dentry, mnt, name, value, size,
- flags);
+ flags, file);
}
void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
@@ -455,30 +456,32 @@ void security_inode_post_setxattr(struct
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return;
- security_ops->inode_post_setxattr(dentry, mnt, name, value, size, flags);
+ security_ops->inode_post_setxattr(dentry, mnt, name, value, size,
+ flags);
}
int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name)
+ char *name, struct file *file)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- return security_ops->inode_getxattr(dentry, mnt, name);
+ return security_ops->inode_getxattr(dentry, mnt, name, file);
}
-int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt)
+int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
+ struct file *file)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- return security_ops->inode_listxattr(dentry, mnt);
+ return security_ops->inode_listxattr(dentry, mnt, file);
}
int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name)
+ char *name, struct file *file)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- return security_ops->inode_removexattr(dentry, mnt, name);
+ return security_ops->inode_removexattr(dentry, mnt, name, file);
}
int security_inode_need_killpriv(struct dentry *dentry)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2334,7 +2334,7 @@ static int selinux_inode_setotherxattr(s
static int selinux_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
char *name, void *value, size_t size,
- int flags)
+ int flags, struct file *file)
{
struct task_security_struct *tsec = current->security;
struct inode *inode = dentry->d_inode;
@@ -2410,18 +2410,20 @@ static void selinux_inode_post_setxattr(
}
static int selinux_inode_getxattr (struct dentry *dentry, struct vfsmount *mnt,
- char *name)
+ char *name, struct file *file)
{
return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
}
-static int selinux_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt)
+static int selinux_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt,
+ struct file *file)
{
return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
}
static int selinux_inode_removexattr (struct dentry *dentry,
- struct vfsmount *mnt, char *name)
+ struct vfsmount *mnt, char *name,
+ struct file *file)
{
if (strcmp(name, XATTR_NAME_SELINUX))
return selinux_inode_setotherxattr(dentry, name);

View File

@@ -1,55 +0,0 @@
security-create.diff
remove_suid.diff
vfs-notify_change.diff
security-setattr.diff
vfs-mkdir.diff
security-mkdir.diff
vfs-mknod.diff
security-mknod.diff
vfs-symlink.diff
security-symlink.diff
security-readlink.diff
vfs-link.diff
security-link.diff
vfs-rmdir.diff
security-rmdir.diff
fix-vfs_rmdir.diff
vfs-unlink.diff
security-unlink.diff
vfs-rename.diff
security-rename.diff
vfs-setxattr.diff
security-setxattr.diff
vfs-getxattr.diff
security-getxattr.diff
vfs-listxattr.diff
security-listxattr.diff
vfs-removexattr.diff
security-removexattr.diff
unambiguous-__d_path.diff
mount-consistent-__d_path.diff
d_namespace_path.diff
__d_path-keep-connected.diff
fsetattr.diff
fsetattr-reintro-ATTR_FILE.diff
file-handle-ops.diff
security-xattr-file.diff
sysctl-pathname.diff
parent-permission.diff
do_path_lookup-nameidata.diff
sys_fchdir-nameidata.diff
file_permission-nameidata.diff
apparmor-audit.diff
apparmor-main.diff
apparmor-lsm.diff
apparmor-module_interface.diff
apparmor-misc.diff
apparmor-intree.diff
apparmor-network.diff
apparmor-rlimits.diff
audit-log-type-in-syslog.diff

View File

@@ -1,51 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Switch to vfs_permission() in sys_fchdir()
Switch from file_permission() to vfs_permission() in sys_fchdir(): this
avoids calling permission() with a NULL nameidata here.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/open.c | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
--- a/fs/open.c
+++ b/fs/open.c
@@ -501,10 +501,8 @@ out:
asmlinkage long sys_fchdir(unsigned int fd)
{
+ struct nameidata nd;
struct file *file;
- struct dentry *dentry;
- struct inode *inode;
- struct vfsmount *mnt;
int error;
error = -EBADF;
@@ -512,17 +510,17 @@ asmlinkage long sys_fchdir(unsigned int
if (!file)
goto out;
- dentry = file->f_path.dentry;
- mnt = file->f_path.mnt;
- inode = dentry->d_inode;
+ nd.dentry = file->f_path.dentry;
+ nd.mnt = file->f_path.mnt;
+ nd.flags = 0;
error = -ENOTDIR;
- if (!S_ISDIR(inode->i_mode))
+ if (!S_ISDIR(nd.dentry->d_inode->i_mode))
goto out_putf;
- error = file_permission(file, MAY_EXEC);
+ error = vfs_permission(&nd, MAY_EXEC);
if (!error)
- set_fs_pwd(current->fs, mnt, dentry);
+ set_fs_pwd(current->fs, nd.mnt, nd.dentry);
out_putf:
fput(file);
out:

View File

@@ -1,111 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Factor out sysctl pathname code
Convert the selinux sysctl pathname computation code into a standalone
function.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
Reviewed-by: James Morris <jmorris@namei.org>
---
include/linux/sysctl.h | 2 ++
kernel/sysctl.c | 27 +++++++++++++++++++++++++++
security/selinux/hooks.c | 35 +++++------------------------------
3 files changed, 34 insertions(+), 30 deletions(-)
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -983,6 +983,8 @@ extern int proc_doulongvec_minmax(struct
extern int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int,
struct file *, void __user *, size_t *, loff_t *);
+extern char *sysctl_pathname(ctl_table *, char *, int);
+
extern int do_sysctl (int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen);
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1327,6 +1327,33 @@ struct ctl_table_header *sysctl_head_nex
return NULL;
}
+char *sysctl_pathname(ctl_table *table, char *buffer, int buflen)
+{
+ if (buflen < 1)
+ return NULL;
+ buffer += --buflen;
+ *buffer = '\0';
+
+ while (table) {
+ int namelen = strlen(table->procname);
+
+ if (buflen < namelen + 1)
+ return NULL;
+ buflen -= namelen + 1;
+ buffer -= namelen;
+ memcpy(buffer, table->procname, namelen);
+ *--buffer = '/';
+ table = table->parent;
+ }
+ if (buflen < 4)
+ return NULL;
+ buffer -= 4;
+ memcpy(buffer, "/sys", 4);
+
+ return buffer;
+}
+EXPORT_SYMBOL(sysctl_pathname);
+
#ifdef CONFIG_SYSCTL_SYSCALL
int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1431,40 +1431,15 @@ static int selinux_capable(struct task_s
static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
{
- int buflen, rc;
- char *buffer, *path, *end;
+ char *buffer, *path;
+ int rc = -ENOMEM;
- rc = -ENOMEM;
buffer = (char*)__get_free_page(GFP_KERNEL);
if (!buffer)
goto out;
-
- buflen = PAGE_SIZE;
- end = buffer+buflen;
- *--end = '\0';
- buflen--;
- path = end-1;
- *path = '/';
- while (table) {
- const char *name = table->procname;
- size_t namelen = strlen(name);
- buflen -= namelen + 1;
- if (buflen < 0)
- goto out_free;
- end -= namelen;
- memcpy(end, name, namelen);
- *--end = '/';
- path = end;
- table = table->parent;
- }
- buflen -= 4;
- if (buflen < 0)
- goto out_free;
- end -= 4;
- memcpy(end, "/sys", 4);
- path = end;
- rc = security_genfs_sid("proc", path, tclass, sid);
-out_free:
+ path = sysctl_pathname(table, buffer, PAGE_SIZE);
+ if (path)
+ rc = security_genfs_sid("proc", path, tclass, sid);
free_page((unsigned long)buffer);
out:
return rc;

View File

@@ -1,268 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: 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 <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
---
fs/dcache.c | 169 ++++++++++++++++++++++++++++++++++--------------------------
1 file changed, 98 insertions(+), 71 deletions(-)
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1764,52 +1764,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);
@@ -1823,33 +1822,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 = '/';
- return retval;
+out:
+ spin_unlock(&dcache_lock);
+ return buffer;
global_root:
+ /*
+ * We went past the (vfsmount, dentry) we were looking for and have
+ * either hit a root dentry, a lazily unmounted dentry, an
+ * unconnected dentry, or the file is on a pseudo filesystem.
+ */
namelen = dentry->d_name.len;
- buflen -= namelen;
- if (buflen < 0)
+ is_slash = (namelen == 1 && *dentry->d_name.name == '/');
+ if (is_slash || (dentry->d_sb->s_flags & MS_NOUSER)) {
+ /*
+ * Make sure we won't return a pathname starting with '/'.
+ *
+ * Historically, we also glue together the root dentry and
+ * remaining name for pseudo filesystems like pipefs, which
+ * have the MS_NOUSER flag set. This results in pathnames
+ * like "pipe:[439336]".
+ */
+ if (*buffer == '/') {
+ buffer++;
+ buflen++;
+ }
+ if (is_slash)
+ goto out;
+ }
+ if (buflen < namelen)
goto Elong;
- retval -= namelen-1; /* hit the slash */
- memcpy(retval, dentry->d_name.name, namelen);
- return retval;
+ buffer -= namelen;
+ memcpy(buffer, dentry->d_name.name, namelen);
+ goto out;
+
Elong:
- return ERR_PTR(-ENAMETOOLONG);
+ buffer = ERR_PTR(-ENAMETOOLONG);
+ goto out;
+}
+
+static char *__connect_d_path(char *path, char *buffer)
+{
+ if (!IS_ERR(path) && *path != '/') {
+ /* Pretend that disconnected paths are hanging off the root. */
+ if (path == buffer)
+ path = ERR_PTR(-ENAMETOOLONG);
+ else
+ *--path = '/';
+ }
+ return path;
}
/* write full pathname into buffer and return start of pathname */
-char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
- char *buf, int buflen)
+char *d_path(struct dentry *dentry, struct vfsmount *vfsmnt, char *buf,
+ int buflen)
{
char *res;
struct vfsmount *rootmnt;
@@ -1869,9 +1907,8 @@ char * d_path(struct dentry *dentry, str
rootmnt = mntget(current->fs->rootmnt);
root = dget(current->fs->root);
read_unlock(&current->fs->lock);
- spin_lock(&dcache_lock);
- res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen);
- spin_unlock(&dcache_lock);
+ res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen, 0);
+ res = __connect_d_path(res, buf);
dput(root);
mntput(rootmnt);
return res;
@@ -1918,10 +1955,10 @@ char *dynamic_dname(struct dentry *dentr
*/
asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
{
- int error;
+ int error, len;
struct vfsmount *pwdmnt, *rootmnt;
struct dentry *pwd, *root;
- char *page = (char *) __get_free_page(GFP_USER);
+ char *page = (char *) __get_free_page(GFP_USER), *cwd;
if (!page)
return -ENOMEM;
@@ -1933,29 +1970,19 @@ asmlinkage long sys_getcwd(char __user *
root = dget(current->fs->root);
read_unlock(&current->fs->lock);
- error = -ENOENT;
- /* Has the current directory has been unlinked? */
- spin_lock(&dcache_lock);
- if (pwd->d_parent == pwd || !d_unhashed(pwd)) {
- unsigned long len;
- char * cwd;
-
- cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE);
- spin_unlock(&dcache_lock);
-
- error = PTR_ERR(cwd);
- if (IS_ERR(cwd))
- goto out;
-
- error = -ERANGE;
- len = PAGE_SIZE + page - cwd;
- if (len <= size) {
- error = len;
- if (copy_to_user(buf, cwd, len))
- error = -EFAULT;
- }
- } else
- spin_unlock(&dcache_lock);
+ cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE, 1);
+ cwd = __connect_d_path(cwd, page);
+ error = PTR_ERR(cwd);
+ if (IS_ERR(cwd))
+ goto out;
+
+ error = -ERANGE;
+ len = PAGE_SIZE + page - cwd;
+ if (len <= size) {
+ error = len;
+ if (copy_to_user(buf, cwd, len))
+ error = -EFAULT;
+ }
out:
dput(pwd);

View File

@@ -1,190 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: 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 <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
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
@@ -1496,7 +1496,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
@@ -408,11 +408,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;
@@ -420,7 +421,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
@@ -501,13 +502,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)
@@ -519,14 +520,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)) {
@@ -536,7 +538,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)) {
@@ -2001,7 +2003,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
@@ -105,7 +105,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;
@@ -277,7 +278,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;
@@ -297,7 +299,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;
@@ -320,7 +322,7 @@ sys_getxattr(char __user *path, char __u
error = user_path_walk(path, &nd);
if (error)
return error;
- error = getxattr(nd.dentry, name, value, size);
+ error = getxattr(nd.dentry, nd.mnt, name, value, size);
path_release(&nd);
return error;
}
@@ -335,7 +337,7 @@ sys_lgetxattr(char __user *path, char __
error = user_path_walk_link(path, &nd);
if (error)
return error;
- error = getxattr(nd.dentry, name, value, size);
+ error = getxattr(nd.dentry, nd.mnt, name, value, size);
path_release(&nd);
return error;
}
@@ -350,7 +352,7 @@ sys_fgetxattr(int fd, char __user *name,
if (!f)
return error;
audit_inode(NULL, f->f_path.dentry);
- error = getxattr(f->f_path.dentry, name, value, size);
+ error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size);
fput(f);
return error;
}
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -79,7 +79,8 @@ __be32 nfsd_setattr(struct svc_rqst *,
#ifdef CONFIG_NFSD_V4
__be32 nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
struct nfs4_acl *);
-int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
+int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *,
+ struct vfsmount *mnt, struct nfs4_acl **);
#endif /* CONFIG_NFSD_V4 */
__be32 nfsd_create(struct svc_rqst *, struct svc_fh *,
char *name, int len, struct iattr *attrs,
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -46,7 +46,8 @@ struct xattr_handler {
size_t size, int flags);
};
-ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t);
+ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, char *, void *,
+ size_t);
ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
int vfs_setxattr(struct dentry *, struct vfsmount *, char *, void *, size_t,
int);

View File

@@ -1,90 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: 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 <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
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
@@ -402,19 +402,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
@@ -2331,7 +2331,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;
@@ -2409,7 +2409,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
@@ -1589,7 +1589,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
@@ -1071,7 +1071,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 *);

View File

@@ -1,102 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Add a struct vfsmount parameter to vfs_listxattr()
The vfsmount will be passed down to the LSM hook so that LSMs can compute
pathnames.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/xattr.c | 25 ++++++++++++++-----------
include/linux/xattr.h | 3 ++-
2 files changed, 16 insertions(+), 12 deletions(-)
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -142,18 +142,20 @@ vfs_getxattr(struct dentry *dentry, stru
EXPORT_SYMBOL_GPL(vfs_getxattr);
ssize_t
-vfs_listxattr(struct dentry *d, char *list, size_t size)
+vfs_listxattr(struct dentry *dentry, struct vfsmount *mnt, char *list,
+ size_t size)
{
+ struct inode *inode = dentry->d_inode;
ssize_t error;
- error = security_inode_listxattr(d);
+ error = security_inode_listxattr(dentry);
if (error)
return error;
error = -EOPNOTSUPP;
- if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
- error = d->d_inode->i_op->listxattr(d, list, size);
- } else {
- error = security_inode_listsecurity(d->d_inode, list, size);
+ if (inode->i_op && inode->i_op->listxattr)
+ error = inode->i_op->listxattr(dentry, list, size);
+ else {
+ error = security_inode_listsecurity(inode, list, size);
if (size && error > size)
error = -ERANGE;
}
@@ -361,7 +363,8 @@ sys_fgetxattr(int fd, char __user *name,
* Extended attribute LIST operations
*/
static ssize_t
-listxattr(struct dentry *d, char __user *list, size_t size)
+listxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *list,
+ size_t size)
{
ssize_t error;
char *klist = NULL;
@@ -374,7 +377,7 @@ listxattr(struct dentry *d, char __user
return -ENOMEM;
}
- error = vfs_listxattr(d, klist, size);
+ error = vfs_listxattr(dentry, mnt, klist, size);
if (error > 0) {
if (size && copy_to_user(list, klist, error))
error = -EFAULT;
@@ -396,7 +399,7 @@ sys_listxattr(char __user *path, char __
error = user_path_walk(path, &nd);
if (error)
return error;
- error = listxattr(nd.dentry, list, size);
+ error = listxattr(nd.dentry, nd.mnt, list, size);
path_release(&nd);
return error;
}
@@ -410,7 +413,7 @@ sys_llistxattr(char __user *path, char _
error = user_path_walk_link(path, &nd);
if (error)
return error;
- error = listxattr(nd.dentry, list, size);
+ error = listxattr(nd.dentry, nd.mnt, list, size);
path_release(&nd);
return error;
}
@@ -425,7 +428,7 @@ sys_flistxattr(int fd, char __user *list
if (!f)
return error;
audit_inode(NULL, f->f_path.dentry);
- error = listxattr(f->f_path.dentry, list, size);
+ error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size);
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 dentry *, struct vfsmount *, char *, void *,
size_t);
-ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
+ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list,
+ size_t size);
int vfs_setxattr(struct dentry *, struct vfsmount *, char *, void *, size_t,
int);
int vfs_removexattr(struct dentry *, char *);

View File

@@ -1,137 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Add struct vfsmount parameter to vfs_mkdir()
The vfsmount will be passed down to the LSM hook so that LSMs can compute
pathnames.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/ecryptfs/inode.c | 5 ++++-
fs/namei.c | 5 +++--
fs/nfsd/nfs4recover.c | 3 ++-
fs/nfsd/vfs.c | 8 +++++---
include/linux/fs.h | 2 +-
kernel/cgroup.c | 2 +-
6 files changed, 16 insertions(+), 9 deletions(-)
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -488,11 +488,14 @@ static int ecryptfs_mkdir(struct inode *
{
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_mkdir(lower_dir_dentry->d_inode, lower_dentry, mode);
+ rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, lower_mnt,
+ mode);
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
@@ -1998,7 +1998,8 @@ asmlinkage long sys_mknod(const char __u
return sys_mknodat(AT_FDCWD, filename, mode, dev);
}
-int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+int vfs_mkdir(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
+ int mode)
{
int error = may_create(dir, dentry, NULL);
@@ -2042,7 +2043,7 @@ asmlinkage long sys_mkdirat(int dfd, con
if (!IS_POSIXACL(nd.dentry->d_inode))
mode &= ~current->fs->umask;
- error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
+ error = vfs_mkdir(nd.dentry->d_inode, dentry, nd.mnt, mode);
dput(dentry);
out_unlock:
mutex_unlock(&nd.dentry->d_inode->i_mutex);
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -154,7 +154,8 @@ nfsd4_create_clid_dir(struct nfs4_client
dprintk("NFSD: nfsd4_create_clid_dir: DIRECTORY EXISTS\n");
goto out_put;
}
- status = vfs_mkdir(rec_dir.dentry->d_inode, dentry, S_IRWXU);
+ status = vfs_mkdir(rec_dir.dentry->d_inode, dentry, rec_dir.mnt,
+ S_IRWXU);
out_put:
dput(dentry);
out_unlock:
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1165,6 +1165,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
int type, dev_t rdev, struct svc_fh *resfhp)
{
struct dentry *dentry, *dchild = NULL;
+ struct svc_export *exp;
struct inode *dirp;
__be32 err;
int host_err;
@@ -1181,6 +1182,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
goto out;
dentry = fhp->fh_dentry;
+ exp = fhp->fh_export;
dirp = dentry->d_inode;
err = nfserr_notdir;
@@ -1197,7 +1199,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
host_err = PTR_ERR(dchild);
if (IS_ERR(dchild))
goto out_nfserr;
- err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
+ err = fh_compose(resfhp, exp, dchild, fhp);
if (err)
goto out;
} else {
@@ -1236,7 +1238,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
break;
case S_IFDIR:
- host_err = vfs_mkdir(dirp, dchild, iap->ia_mode);
+ host_err = vfs_mkdir(dirp, dchild, exp->ex_mnt, iap->ia_mode);
break;
case S_IFCHR:
case S_IFBLK:
@@ -1251,7 +1253,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
if (host_err < 0)
goto out_nfserr;
- if (EX_ISSYNC(fhp->fh_export)) {
+ if (EX_ISSYNC(exp)) {
err = nfserrno(nfsd_sync_dir(dentry));
write_inode_now(dchild->d_inode, 1);
}
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1068,7 +1068,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 *, int);
+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_symlink(struct inode *, struct dentry *, const char *, int);
extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -2611,7 +2611,7 @@ int cgroup_clone(struct task_struct *tsk
}
/* Create the cgroup directory, which also creates the cgroup */
- ret = vfs_mkdir(inode, dentry, S_IFDIR | 0755);
+ ret = vfs_mkdir(inode, dentry, NULL, S_IFDIR | 0755);
child = __d_cgrp(dentry);
dput(dentry);
if (ret) {

View File

@@ -1,98 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: 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 <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
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
@@ -551,11 +551,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
@@ -1918,7 +1918,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);
@@ -1970,11 +1971,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
@@ -1244,7 +1244,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
@@ -1069,7 +1069,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
@@ -839,7 +839,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);

View File

@@ -1,387 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: 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 <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
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 | 2 +-
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, 44 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 = inode->i_mode;
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -862,6 +862,7 @@ 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;
@@ -872,6 +873,7 @@ static int ecryptfs_setattr(struct dentr
inode = dentry->d_inode;
lower_inode = ecryptfs_inode_to_lower(inode);
lower_dentry = ecryptfs_dentry_to_lower(dentry);
+ lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
mutex_lock(&crypt_stat->cs_mutex);
if (S_ISDIR(dentry->d_inode->i_mode))
crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
@@ -922,7 +924,7 @@ static int ecryptfs_setattr(struct dentr
if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
ia->ia_valid &= ~ATTR_MODE;
- 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
@@ -1784,7 +1784,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, core_limit);
--- 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
@@ -1660,7 +1660,7 @@ int may_open(struct nameidata *nd, int a
if (!error) {
DQUOT_INIT(inode);
- error = do_truncate(dentry, 0,
+ error = do_truncate(dentry, nd->mnt, 0,
ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
NULL);
}
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -388,7 +388,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);
}
@@ -943,13 +943,13 @@ out:
return err;
}
-static void kill_suid(struct dentry *dentry)
+static void kill_suid(struct dentry *dentry, struct vfsmount *mnt)
{
struct iattr ia;
ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
mutex_lock(&dentry->d_inode->i_mutex);
- notify_change(dentry, &ia);
+ notify_change(dentry, mnt, &ia);
mutex_unlock(&dentry->d_inode->i_mutex);
}
@@ -1008,7 +1008,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, s
/* clear setuid/setgid flag after write */
if (host_err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID)))
- kill_suid(dentry);
+ kill_suid(dentry, exp->ex_mnt);
if (host_err >= 0 && stable) {
static ino_t last_ino;
--- a/fs/open.c
+++ b/fs/open.c
@@ -194,8 +194,8 @@ out:
return error;
}
-int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
- struct file *filp)
+int do_truncate(struct dentry *dentry, struct vfsmount *mnt, loff_t length,
+ unsigned int time_attrs, struct file *filp)
{
int err;
struct iattr newattrs;
@@ -215,7 +215,7 @@ int do_truncate(struct dentry *dentry, l
newattrs.ia_valid |= should_remove_suid(dentry);
mutex_lock(&dentry->d_inode->i_mutex);
- err = notify_change(dentry, &newattrs);
+ err = notify_change(dentry, mnt, &newattrs);
mutex_unlock(&dentry->d_inode->i_mutex);
return err;
}
@@ -271,7 +271,7 @@ static long do_sys_truncate(const char _
error = locks_verify_truncate(inode, NULL, length);
if (!error) {
DQUOT_INIT(inode);
- error = do_truncate(nd.dentry, length, 0, NULL);
+ error = do_truncate(nd.dentry, nd.mnt, length, 0, NULL);
}
put_write_and_out:
@@ -324,7 +324,8 @@ static long do_sys_ftruncate(unsigned in
error = locks_verify_truncate(inode, file, length);
if (!error)
- error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file);
+ error = do_truncate(dentry, file->f_path.mnt, length,
+ ATTR_MTIME|ATTR_CTIME, file);
out_putf:
fput(file);
out:
@@ -582,7 +583,7 @@ asmlinkage long sys_fchmod(unsigned int
mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
- err = notify_change(dentry, &newattrs);
+ err = notify_change(dentry, file->f_path.mnt, &newattrs);
mutex_unlock(&inode->i_mutex);
out_putf:
@@ -617,7 +618,7 @@ asmlinkage long sys_fchmodat(int dfd, co
mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
- error = notify_change(nd.dentry, &newattrs);
+ error = notify_change(nd.dentry, nd.mnt, &newattrs);
mutex_unlock(&inode->i_mutex);
dput_and_out:
@@ -631,7 +632,8 @@ asmlinkage long sys_chmod(const char __u
return sys_fchmodat(AT_FDCWD, filename, mode);
}
-static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
+static int chown_common(struct dentry * dentry, struct vfsmount *mnt,
+ uid_t user, gid_t group)
{
struct inode * inode;
int error;
@@ -661,7 +663,7 @@ static int chown_common(struct dentry *
newattrs.ia_valid |=
ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
mutex_lock(&inode->i_mutex);
- error = notify_change(dentry, &newattrs);
+ error = notify_change(dentry, mnt, &newattrs);
mutex_unlock(&inode->i_mutex);
out:
return error;
@@ -675,7 +677,7 @@ asmlinkage long sys_chown(const char __u
error = user_path_walk(filename, &nd);
if (error)
goto out;
- error = chown_common(nd.dentry, user, group);
+ error = chown_common(nd.dentry, nd.mnt, user, group);
path_release(&nd);
out:
return error;
@@ -695,7 +697,7 @@ asmlinkage long sys_fchownat(int dfd, co
error = __user_walk_fd(dfd, filename, follow, &nd);
if (error)
goto out;
- error = chown_common(nd.dentry, user, group);
+ error = chown_common(nd.dentry, nd.mnt, user, group);
path_release(&nd);
out:
return error;
@@ -709,7 +711,7 @@ asmlinkage long sys_lchown(const char __
error = user_path_walk_link(filename, &nd);
if (error)
goto out;
- error = chown_common(nd.dentry, user, group);
+ error = chown_common(nd.dentry, nd.mnt, user, group);
path_release(&nd);
out:
return error;
@@ -728,7 +730,7 @@ asmlinkage long sys_fchown(unsigned int
dentry = file->f_path.dentry;
audit_inode(NULL, dentry);
- error = chown_common(dentry, user, group);
+ error = chown_common(dentry, file->f_path.mnt, user, group);
fput(file);
out:
return error;
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -485,7 +485,7 @@ reiserfs_xattr_set(struct inode *inode,
newattrs.ia_size = buffer_size;
newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
mutex_lock_nested(&xinode->i_mutex, I_MUTEX_XATTR);
- err = notify_change(fp->f_path.dentry, &newattrs);
+ err = notify_change(fp->f_path.dentry, NULL, &newattrs);
if (err)
goto out_filp;
@@ -825,7 +825,7 @@ reiserfs_chown_xattrs_filler(void *buf,
}
if (!S_ISDIR(xafile->d_inode->i_mode))
- err = notify_change(xafile, attrs);
+ err = notify_change(xafile, NULL, attrs);
dput(xafile);
return err;
@@ -877,7 +877,7 @@ int reiserfs_chown_xattrs(struct inode *
goto out_dir;
}
- err = notify_change(dir, attrs);
+ err = notify_change(dir, NULL, attrs);
unlock_kernel();
out_dir:
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -610,7 +610,7 @@ int sysfs_chmod_file(struct kobject *kob
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
- rc = notify_change(victim, &newattrs);
+ rc = notify_change(victim, NULL, &newattrs);
if (rc == 0) {
mutex_lock(&sysfs_mutex);
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -54,7 +54,7 @@ long do_utimes(int dfd, char __user *fil
{
int error;
struct nameidata nd;
- struct dentry *dentry;
+ struct path path;
struct inode *inode;
struct iattr newattrs;
struct file *f = NULL;
@@ -77,16 +77,17 @@ long do_utimes(int dfd, char __user *fil
f = fget(dfd);
if (!f)
goto out;
- dentry = f->f_path.dentry;
+ path = f->f_path;
} else {
error = __user_walk_fd(dfd, filename, (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW, &nd);
if (error)
goto out;
- dentry = nd.dentry;
+ path.dentry = nd.dentry;
+ path.mnt = nd.mnt;
}
- inode = dentry->d_inode;
+ inode = path.dentry->d_inode;
error = -EROFS;
if (IS_RDONLY(inode))
@@ -131,7 +132,7 @@ long do_utimes(int dfd, char __user *fil
}
}
mutex_lock(&inode->i_mutex);
- error = notify_change(dentry, &newattrs);
+ error = notify_change(path.dentry, path.mnt, &newattrs);
mutex_unlock(&inode->i_mutex);
dput_and_out:
if (f)
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1536,8 +1536,8 @@ static inline int break_lease(struct ino
/* fs/open.c */
-extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
- struct file *filp);
+extern int do_truncate(struct dentry *, struct vfsmount *, loff_t start,
+ unsigned int time_attrs, struct file *filp);
extern long do_sys_open(int dfd, const char __user *filename, int flags,
int mode);
extern struct file *filp_open(const char *, int, int);
@@ -1693,7 +1693,7 @@ extern int do_remount_sb(struct super_bl
#ifdef CONFIG_BLOCK
extern sector_t bmap(struct inode *, sector_t);
#endif
-extern int notify_change(struct dentry *, struct iattr *);
+extern int notify_change(struct dentry *, struct vfsmount *, struct iattr *);
extern int permission(struct inode *, int, struct nameidata *);
extern int generic_permission(struct inode *, int,
int (*check_acl)(struct inode *, int));
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1615,7 +1615,7 @@ int __remove_suid(struct path *path, int
struct iattr newattrs;
newattrs.ia_valid = ATTR_FORCE | kill;
- return notify_change(path->dentry, &newattrs);
+ return notify_change(path->dentry, path->mnt, &newattrs);
}
int remove_suid(struct path *path)
--- a/mm/tiny-shmem.c
+++ b/mm/tiny-shmem.c
@@ -81,7 +81,7 @@ struct file *shmem_file_setup(char *name
inode->i_nlink = 0; /* It is unlinked */
/* notify everyone as to the change of file size */
- error = do_truncate(dentry, size, 0, file);
+ error = do_truncate(dentry, file->f_path.mnt, size, 0, file);
if (error < 0)
goto close_file;

View File

@@ -1,111 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Add a struct vfsmount parameter to vfs_removexattr()
The vfsmount will be passed down to the LSM hook so that LSMs can compute
pathnames.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/nfsd/vfs.c | 7 ++++---
fs/xattr.c | 12 ++++++------
include/linux/xattr.h | 2 +-
3 files changed, 11 insertions(+), 10 deletions(-)
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -2016,6 +2016,7 @@ nfsd_get_posix_acl(struct svc_fh *fhp, i
int
nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
{
+ struct vfsmount *mnt;
struct inode *inode = fhp->fh_dentry->d_inode;
char *name;
void *value = NULL;
@@ -2048,14 +2049,14 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i
} else
size = 0;
+ mnt = fhp->fh_export->ex_mnt;
if (size)
- error = vfs_setxattr(fhp->fh_dentry, fhp->fh_export->ex_mnt,
- name, value, size,0);
+ error = vfs_setxattr(fhp->fh_dentry, mnt, name, value, size,0);
else {
if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
error = 0;
else {
- error = vfs_removexattr(fhp->fh_dentry, name);
+ error = vfs_removexattr(fhp->fh_dentry, mnt, name);
if (error == -ENODATA)
error = 0;
}
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -164,7 +164,7 @@ vfs_listxattr(struct dentry *dentry, str
EXPORT_SYMBOL_GPL(vfs_listxattr);
int
-vfs_removexattr(struct dentry *dentry, char *name)
+vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name)
{
struct inode *inode = dentry->d_inode;
int error;
@@ -437,7 +437,7 @@ sys_flistxattr(int fd, char __user *list
* Extended attribute REMOVE operations
*/
static long
-removexattr(struct dentry *d, char __user *name)
+removexattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name)
{
int error;
char kname[XATTR_NAME_MAX + 1];
@@ -448,7 +448,7 @@ removexattr(struct dentry *d, char __use
if (error < 0)
return error;
- return vfs_removexattr(d, kname);
+ return vfs_removexattr(dentry, mnt, kname);
}
asmlinkage long
@@ -460,7 +460,7 @@ sys_removexattr(char __user *path, char
error = user_path_walk(path, &nd);
if (error)
return error;
- error = removexattr(nd.dentry, name);
+ error = removexattr(nd.dentry, nd.mnt, name);
path_release(&nd);
return error;
}
@@ -474,7 +474,7 @@ sys_lremovexattr(char __user *path, char
error = user_path_walk_link(path, &nd);
if (error)
return error;
- error = removexattr(nd.dentry, name);
+ error = removexattr(nd.dentry, nd.mnt, name);
path_release(&nd);
return error;
}
@@ -491,7 +491,7 @@ sys_fremovexattr(int fd, char __user *na
return error;
dentry = f->f_path.dentry;
audit_inode(NULL, dentry);
- error = removexattr(dentry, name);
+ error = removexattr(dentry, f->f_path.mnt, name);
fput(f);
return error;
}
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -52,7 +52,7 @@ ssize_t vfs_listxattr(struct dentry *d,
size_t size);
int vfs_setxattr(struct dentry *, struct vfsmount *, char *, void *, size_t,
int);
-int vfs_removexattr(struct dentry *, char *);
+int vfs_removexattr(struct dentry *, struct vfsmount *, char *);
ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);

View File

@@ -1,125 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Add struct vfsmount parameters to vfs_rename()
The vfsmount will be passed down to the LSM hook so that LSMs can compute
pathnames.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/ecryptfs/inode.c | 7 ++++++-
fs/namei.c | 19 ++++++++++++-------
fs/nfsd/vfs.c | 3 ++-
include/linux/fs.h | 2 +-
4 files changed, 21 insertions(+), 10 deletions(-)
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -589,19 +589,24 @@ ecryptfs_rename(struct inode *old_dir, s
{
int rc;
struct dentry *lower_old_dentry;
+ struct vfsmount *lower_old_mnt;
struct dentry *lower_new_dentry;
+ struct vfsmount *lower_new_mnt;
struct dentry *lower_old_dir_dentry;
struct dentry *lower_new_dir_dentry;
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_old_dir_dentry = dget_parent(lower_old_dentry);
lower_new_dir_dentry = dget_parent(lower_new_dentry);
lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
- lower_new_dir_dentry->d_inode, lower_new_dentry);
+ lower_old_mnt, lower_new_dir_dentry->d_inode,
+ lower_new_dentry, lower_new_mnt);
if (rc)
goto out_lock;
fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode, NULL);
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2464,7 +2464,8 @@ asmlinkage long sys_link(const char __us
* locking].
*/
static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
+ struct vfsmount *old_mnt, struct inode *new_dir,
+ struct dentry *new_dentry, struct vfsmount *new_mnt)
{
int error = 0;
struct inode *target;
@@ -2507,7 +2508,8 @@ static int vfs_rename_dir(struct inode *
}
static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
+ struct vfsmount *old_mnt, struct inode *new_dir,
+ struct dentry *new_dentry, struct vfsmount *new_mnt)
{
struct inode *target;
int error;
@@ -2535,7 +2537,8 @@ static int vfs_rename_other(struct inode
}
int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
+ struct vfsmount *old_mnt, struct inode *new_dir,
+ struct dentry *new_dentry, struct vfsmount *new_mnt)
{
int error;
int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
@@ -2564,9 +2567,11 @@ int vfs_rename(struct inode *old_dir, st
old_name = fsnotify_oldname_init(old_dentry->d_name.name);
if (is_dir)
- error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
+ error = vfs_rename_dir(old_dir, old_dentry, old_mnt,
+ new_dir, new_dentry, new_mnt);
else
- error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
+ error = vfs_rename_other(old_dir, old_dentry, old_mnt,
+ new_dir, new_dentry, new_mnt);
if (!error) {
const char *new_name = old_dentry->d_name.name;
fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir,
@@ -2638,8 +2643,8 @@ static int do_rename(int olddfd, const c
if (new_dentry == trap)
goto exit5;
- error = vfs_rename(old_dir->d_inode, old_dentry,
- new_dir->d_inode, new_dentry);
+ error = vfs_rename(old_dir->d_inode, old_dentry, oldnd.mnt,
+ new_dir->d_inode, new_dentry, newnd.mnt);
exit5:
dput(new_dentry);
exit4:
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1683,7 +1683,8 @@ nfsd_rename(struct svc_rqst *rqstp, stru
host_err = -EPERM;
} else
#endif
- host_err = vfs_rename(fdir, odentry, tdir, ndentry);
+ host_err = vfs_rename(fdir, odentry, ffhp->fh_export->ex_mnt,
+ tdir, ndentry, tfhp->fh_export->ex_mnt);
if (!host_err && EX_ISSYNC(tfhp->fh_export)) {
host_err = nfsd_sync_dir(tdentry);
if (!host_err)
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1074,7 +1074,7 @@ extern int vfs_symlink(struct inode *, s
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 *, struct vfsmount *);
-extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
+extern int vfs_rename(struct inode *, struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
/*
* VFS dentry helper functions.

View File

@@ -1,135 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: 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 <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
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
@@ -533,14 +533,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
@@ -2087,7 +2087,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);
@@ -2151,7 +2151,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
@@ -274,7 +274,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
@@ -1719,6 +1719,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;
@@ -1733,6 +1734,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);
@@ -1750,21 +1752,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
@@ -781,7 +781,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
@@ -1072,7 +1072,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 *);

View File

@@ -1,152 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: 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 <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
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
@@ -426,7 +426,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;
@@ -445,7 +446,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;
@@ -458,6 +459,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;
@@ -468,6 +470,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst
return error;
dentry = fhp->fh_dentry;
+ mnt = fhp->fh_export->ex_mnt;
inode = dentry->d_inode;
if (S_ISDIR(inode->i_mode))
flags = NFS4_ACL_DIR;
@@ -478,12 +481,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_release;
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);
out_release:
posix_acl_release(pacl);
@@ -2041,7 +2046,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
@@ -68,8 +68,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;
@@ -192,8 +192,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;
@@ -220,7 +220,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;
}
@@ -235,7 +235,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;
}
@@ -250,7 +250,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;
}
@@ -268,7 +268,7 @@ sys_fsetxattr(int fd, char __user *name,
return error;
dentry = f->f_path.dentry;
audit_inode(NULL, dentry);
- 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 dentry *, char *, void *, size_t);
ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
-int vfs_setxattr(struct dentry *, char *, void *, size_t, int);
+int vfs_setxattr(struct dentry *, struct vfsmount *, char *, void *, size_t,
+ int);
int vfs_removexattr(struct dentry *, char *);
ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);

View File

@@ -1,122 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Add a struct vfsmount parameter to vfs_symlink()
The vfsmount will be passed down to the LSM hook so that LSMs can compute
pathnames.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/ecryptfs/inode.c | 4 +++-
fs/namei.c | 6 ++++--
fs/nfsd/vfs.c | 12 ++++++++----
include/linux/fs.h | 2 +-
4 files changed, 16 insertions(+), 8 deletions(-)
--- a/fs/ecryptfs/inode.c 2007-11-01 16:43:54.000000000 -0400
+++ b/fs/ecryptfs/inode.c 2007-11-01 16:47:29.000000000 -0400
@@ -461,6 +461,7 @@ static int ecryptfs_symlink(struct inode
{
int rc;
struct dentry *lower_dentry;
+ struct vfsmount *lower_mnt;
struct dentry *lower_dir_dentry;
umode_t mode;
char *encoded_symname;
@@ -469,6 +470,7 @@ static int ecryptfs_symlink(struct inode
lower_dentry = ecryptfs_dentry_to_lower(dentry);
dget(lower_dentry);
+ lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
lower_dir_dentry = lock_parent(lower_dentry);
mode = S_IALLUGO;
encoded_symlen = ecryptfs_encode_filename(crypt_stat, symname,
@@ -478,7 +480,7 @@ static int ecryptfs_symlink(struct inode
rc = encoded_symlen;
goto out_lock;
}
- rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry,
+ rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry, lower_mnt,
encoded_symname, mode);
kfree(encoded_symname);
if (rc || !lower_dentry->d_inode)
--- a/fs/namei.c 2007-11-01 16:47:26.000000000 -0400
+++ b/fs/namei.c 2007-11-01 16:47:29.000000000 -0400
@@ -2266,7 +2266,8 @@ asmlinkage long sys_unlink(const char __
return do_unlinkat(AT_FDCWD, pathname);
}
-int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, int mode)
+int vfs_symlink(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
+ const char *oldname, int mode)
{
int error = may_create(dir, dentry, NULL);
@@ -2312,7 +2313,8 @@ asmlinkage long sys_symlinkat(const char
if (IS_ERR(dentry))
goto out_unlock;
- error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO);
+ error = vfs_symlink(nd.dentry->d_inode, dentry, nd.mnt, from,
+ S_IALLUGO);
dput(dentry);
out_unlock:
mutex_unlock(&nd.dentry->d_inode->i_mutex);
--- a/fs/nfsd/vfs.c 2007-11-01 16:43:54.000000000 -0400
+++ b/fs/nfsd/vfs.c 2007-11-01 16:47:29.000000000 -0400
@@ -1489,6 +1489,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
struct iattr *iap)
{
struct dentry *dentry, *dnew;
+ struct svc_export *exp;
__be32 err, cerr;
int host_err;
umode_t mode;
@@ -1515,6 +1516,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
if (iap && (iap->ia_valid & ATTR_MODE))
mode = iap->ia_mode & S_IALLUGO;
+ exp = fhp->fh_export;
if (unlikely(path[plen] != 0)) {
char *path_alloced = kmalloc(plen+1, GFP_KERNEL);
if (path_alloced == NULL)
@@ -1522,20 +1524,22 @@ nfsd_symlink(struct svc_rqst *rqstp, str
else {
strncpy(path_alloced, path, plen);
path_alloced[plen] = 0;
- host_err = vfs_symlink(dentry->d_inode, dnew, path_alloced, mode);
+ host_err = vfs_symlink(dentry->d_inode, dnew,
+ exp->ex_mnt, path_alloced, mode);
kfree(path_alloced);
}
} else
- host_err = vfs_symlink(dentry->d_inode, dnew, path, mode);
+ host_err = vfs_symlink(dentry->d_inode, dnew, exp->ex_mnt, path,
+ mode);
if (!host_err) {
- if (EX_ISSYNC(fhp->fh_export))
+ if (EX_ISSYNC(exp))
host_err = nfsd_sync_dir(dentry);
}
err = nfserrno(host_err);
fh_unlock(fhp);
- cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp);
+ cerr = fh_compose(resfhp, exp, dnew, fhp);
dput(dnew);
if (err==0) err = cerr;
out:
--- a/include/linux/fs.h 2007-11-01 16:43:54.000000000 -0400
+++ b/include/linux/fs.h 2007-11-01 16:47:29.000000000 -0400
@@ -1070,7 +1070,7 @@ extern int vfs_permission(struct nameida
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 *, struct vfsmount *, int, dev_t);
-extern int vfs_symlink(struct inode *, struct dentry *, const char *, int);
+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_rmdir(struct inode *, struct dentry *);
extern int vfs_unlink(struct inode *, struct dentry *);

View File

@@ -1,98 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: 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 <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
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
@@ -444,10 +444,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
@@ -2168,7 +2168,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);
@@ -2232,7 +2232,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
@@ -259,7 +259,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
@@ -1757,7 +1757,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
@@ -1073,7 +1073,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
@@ -744,7 +744,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);

View File

@@ -1,139 +0,0 @@
From: John Johansen <jjohansen@suse.de>
Subject: Fix __d_path to allow for old and new behavior bnc#380763
Fix __d_path so that it can be told whether or not to connect
disconnect path to the root. This is easier and more efficient
than trying to reconnect these paths for d_path and get_cwd
after the fact.
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/dcache.c | 56 ++++++++++++++++++-------------------------------
fs/namespace.c | 2 -
include/linux/dcache.h | 2 -
3 files changed, 23 insertions(+), 37 deletions(-)
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1755,6 +1755,7 @@ shouldnt_be_hashed:
* @buffer: buffer to return value in
* @buflen: buffer length
* @fail_deleted: what to return for deleted files
+ * @disconnect: don't return a path starting with / when disconnected
*
* 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,
@@ -1768,9 +1769,10 @@ shouldnt_be_hashed:
*/
char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
struct path *root, char *buffer, int buflen,
- int fail_deleted)
+ int fail_deleted, int disconnect)
{
- int namelen, is_slash, vfsmount_locked = 0;
+ int namelen, vfsmount_locked = 0;
+ const unsigned char *name;
if (buflen < 2)
return ERR_PTR(-ENAMETOOLONG);
@@ -1832,22 +1834,21 @@ global_root:
* unconnected dentry, or the file is on a pseudo filesystem.
*/
namelen = dentry->d_name.len;
- is_slash = (namelen == 1 && *dentry->d_name.name == '/');
- if (is_slash || (dentry->d_sb->s_flags & MS_NOUSER)) {
- /*
- * Make sure we won't return a pathname starting with '/'.
- *
- * Historically, we also glue together the root dentry and
- * remaining name for pseudo filesystems like pipefs, which
- * have the MS_NOUSER flag set. This results in pathnames
- * like "pipe:[439336]".
- */
- if (*buffer == '/') {
- buffer++;
- buflen++;
- }
- if (is_slash)
- goto out;
+ name = dentry->d_name.name;
+
+ /*
+ * If this is a root dentry, then overwrite the slash. This
+ * will also DTRT with pseudo filesystems which have root
+ * dentries named "foo:".
+ */
+ if (IS_ROOT(dentry)) {
+ buffer++;
+ buflen++;
+ }
+ if (disconnect && *name == '/') {
+ /* Make sure we won't return a pathname starting with '/' */
+ name++;
+ namelen--;
}
if (buflen < namelen)
goto Elong;
@@ -1860,19 +1861,6 @@ Elong:
goto out;
}
-static char *__connect_d_path(char *path, char *buffer, struct dentry *dentry)
-{
- if (!IS_ERR(path) && *path != '/' &&
- !(dentry->d_sb->s_flags & MS_NOUSER)) {
- /* Pretend that disconnected paths are hanging off the root. */
- if (path == buffer)
- path = ERR_PTR(-ENAMETOOLONG);
- else
- *--path = '/';
- }
- return path;
-}
-
/**
* d_path - return the path of a dentry
* @path: path to report
@@ -1905,8 +1893,7 @@ char *d_path(struct path *path, char *bu
root = current->fs->root;
path_get(&current->fs->root);
read_unlock(&current->fs->lock);
- res = __d_path(path->dentry, path->mnt, &root, buf, buflen, 0);
- res = __connect_d_path(res, buf, path->dentry);
+ res = __d_path(path->dentry, path->mnt, &root, buf, buflen, 0, 0);
path_put(&root);
return res;
}
@@ -1966,8 +1953,7 @@ asmlinkage long sys_getcwd(char __user *
path_get(&current->fs->root);
read_unlock(&current->fs->lock);
- cwd = __d_path(pwd.dentry, pwd.mnt, &root, page, PAGE_SIZE, 1);
- cwd = __connect_d_path(cwd, page, pwd.dentry);
+ cwd = __d_path(pwd.dentry, pwd.mnt, &root, page, PAGE_SIZE, 1, 0);
error = PTR_ERR(cwd);
if (IS_ERR(cwd))
goto out;
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1869,7 +1869,7 @@ char *d_namespace_path(struct dentry *de
if (ns_root.mnt)
ns_root.dentry = dget(ns_root.mnt->mnt_root);
spin_unlock(&vfsmount_lock);
- res = __d_path(dentry, vfsmnt, &ns_root, buf, buflen, 1);
+ res = __d_path(dentry, vfsmnt, &ns_root, buf, buflen, 1, 1);
path_put(&root);
path_put(&ns_root);
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -301,7 +301,7 @@ extern int d_validate(struct dentry *, s
*/
extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
extern char *__d_path(struct dentry *, struct vfsmount *, struct path *,
- char *, int, int);
+ char *, int, int, int);
extern char *d_path(struct path *, char *, int);
/* Allocation counts.. */

View File

@@ -1,60 +0,0 @@
From: John Johansen <jjohansen@suse.de>
Subject: AppArmor: Patch AppArmor for 2.6.25 kernel
Add 64 bit capabilities support to AppArmor.
Signed-off-by: John Johansen <jjohansen@suse.de>
---
security/apparmor/lsm.c | 3 ++-
security/apparmor/module_interface.c | 22 ++++++++++++++++++----
2 files changed, 20 insertions(+), 5 deletions(-)
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -462,7 +462,8 @@ static int apparmor_inode_permission(str
/* allow traverse accesses to directories */
mask &= ~MAY_EXEC;
}
- return aa_permission("inode_permission", inode, nd->dentry, nd->mnt,
+ return aa_permission("inode_permission", inode, nd->path.dentry,
+ nd->path.mnt,
mask, check);
}
--- a/security/apparmor/module_interface.c
+++ b/security/apparmor/module_interface.c
@@ -356,15 +356,29 @@ static struct aa_profile *aa_unpack_prof
if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
goto fail;
- if (!aa_is_u32(e, &(profile->capabilities), NULL))
+ if (!aa_is_u32(e, &(profile->capabilities.cap[0]), NULL))
goto fail;
- if (!aa_is_u32(e, &(profile->audit_caps), NULL))
+ if (!aa_is_u32(e, &(profile->audit_caps.cap[0]), NULL))
goto fail;
- if (!aa_is_u32(e, &(profile->quiet_caps), NULL))
+ if (!aa_is_u32(e, &(profile->quiet_caps.cap[0]), NULL))
goto fail;
- if (!aa_is_u32(e, &(profile->set_caps), NULL))
+ if (!aa_is_u32(e, &(profile->set_caps.cap[0]), NULL))
goto fail;
+ if (aa_is_nameX(e, AA_STRUCT, "caps64")) {
+ /* optional upper half of 64 bit caps */
+ if (!aa_is_u32(e, &(profile->capabilities.cap[1]), NULL))
+ goto fail;
+ if (!aa_is_u32(e, &(profile->audit_caps.cap[1]), NULL))
+ goto fail;
+ if (!aa_is_u32(e, &(profile->quiet_caps.cap[1]), NULL))
+ goto fail;
+ if (!aa_is_u32(e, &(profile->set_caps.cap[1]), NULL))
+ goto fail;
+ if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
+ goto fail;
+ }
+
if (!aa_unpack_rlimits(e, profile))
goto fail;

View File

@@ -1,72 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: 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 <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
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)
@@ -119,6 +119,13 @@
#define AUDIT_MAC_UNLBL_STCADD 1416 /* NetLabel: add a static label */
#define AUDIT_MAC_UNLBL_STCDEL 1417 /* NetLabel: del a static label */
+#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_HINT 1504 /* 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_MSG 1799
#define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */
@@ -518,6 +525,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 void audit_log_vformat(struct audit_buffer *ab,
+ const char *fmt, va_list args)
+ __attribute__((format(printf,2,0)));
extern void audit_log_format(struct audit_buffer *ab,
const char *fmt, ...)
__attribute__((format(printf,2,3)));
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1136,8 +1136,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;
@@ -1407,3 +1406,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);

View File

@@ -1,30 +0,0 @@
From: John Johansen <jjohansen@suse.de>
Subject: Add AppArmor LSM to security/Makefile
Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
security/Kconfig | 1 +
security/Makefile | 1 +
2 files changed, 2 insertions(+)
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -124,6 +124,7 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR
source security/selinux/Kconfig
source security/smack/Kconfig
+source security/apparmor/Kconfig
endmenu
--- a/security/Makefile
+++ b/security/Makefile
@@ -16,5 +16,6 @@ obj-$(CONFIG_SECURITY) += security.o d
# Must precede capability.o in order to stack properly.
obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
obj-$(CONFIG_SECURITY_SMACK) += commoncap.o smack/built-in.o
+obj-$(CONFIG_SECURITY_APPARMOR) += commoncap.o apparmor/
obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o
obj-$(CONFIG_SECURITY_ROOTPLUG) += commoncap.o root_plug.o

View File

@@ -1,904 +0,0 @@
From: John Johansen <jjohansen@suse.de>
Subject: AppArmor: Module and LSM hooks
Module parameters, LSM hooks, initialization and teardown.
Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
security/apparmor/lsm.c | 889 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 889 insertions(+)
--- /dev/null
+++ b/security/apparmor/lsm.c
@@ -0,0 +1,889 @@
+/*
+ * 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"
+
+/* Flag indicating whether initialization completed */
+int apparmor_initialized = 0;
+
+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");
+
+/* Boot time disable flag */
+#ifdef CONFIG_SECURITY_APPARMOR_DISABLE
+#define AA_ENABLED_PERMS 0600
+#else
+#define AA_ENABLED_PERMS 0400
+#endif
+static int param_set_aa_enabled(const char *val, struct kernel_param *kp);
+unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
+module_param_call(enabled, param_set_aa_enabled, param_get_aauint,
+ &apparmor_enabled, AA_ENABLED_PERMS);
+MODULE_PARM_DESC(apparmor_enabled, "Enable/Disable Apparmor on boot");
+
+static int __init apparmor_enabled_setup(char *str)
+{
+ apparmor_enabled = simple_strtol(str, NULL, 0);
+ return 1;
+}
+__setup("apparmor=", apparmor_enabled_setup);
+
+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);
+}
+
+/* allow run time disabling of apparmor */
+static int param_set_aa_enabled(const char *val, struct kernel_param *kp)
+{
+ char *endp;
+ unsigned long l;
+
+ if (!apparmor_initialized) {
+ apparmor_enabled = 0;
+ return 0;
+ }
+
+ if (aa_task_context(current))
+ return -EPERM;
+
+ if (!apparmor_enabled)
+ return -EINVAL;
+
+ if (!val)
+ return -EINVAL;
+
+ l = simple_strtoul(val, &endp, 0);
+ if (endp == val || l != 0)
+ return -EINVAL;
+
+ apparmor_enabled = 0;
+ apparmor_disable();
+ return 0;
+}
+
+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;
+ } else {
+ struct aa_task_context *child_cxt =
+ aa_task_context(child);
+
+ error = aa_may_ptrace(cxt, child_cxt ?
+ child_cxt->profile : NULL);
+ if (PROFILE_COMPLAIN(cxt->profile)) {
+ 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;
+ aa_audit_hint(cxt->profile, &sa);
+ }
+ }
+ }
+ rcu_read_unlock();
+
+ return error;
+}
+
+static int apparmor_capable(struct task_struct *task, int cap)
+{
+ int error;
+ struct aa_task_context *cxt;
+
+ /* cap_capable returns 0 on success, else -EPERM */
+ error = cap_capable(task, cap);
+
+ rcu_read_lock();
+ cxt = aa_task_context(task);
+ if (cxt && (!error || cap_raised(cxt->profile->set_caps, cap)))
+ error = aa_capability(cxt, cap);
+ rcu_read_unlock();
+
+ return error;
+}
+
+static int apparmor_sysctl(struct ctl_table *table, int op)
+{
+ struct aa_profile *profile = aa_get_profile(current);
+ int error = 0;
+
+ if (profile) {
+ char *buffer, *name;
+ int mask;
+
+ mask = 0;
+ if (op & 4)
+ mask |= MAY_READ;
+ if (op & 2)
+ mask |= MAY_WRITE;
+
+ error = -ENOMEM;
+ buffer = (char*)__get_free_page(GFP_KERNEL);
+ if (!buffer)
+ goto out;
+ name = sysctl_pathname(table, buffer, PAGE_SIZE);
+ if (name && name - buffer >= 5) {
+ name -= 5;
+ memcpy(name, "/proc", 5);
+ error = aa_perm_path(profile, "sysctl", name, mask, 0);
+ }
+ free_page((unsigned long)buffer);
+ }
+
+out:
+ aa_put_profile(profile);
+ return error;
+}
+
+static int apparmor_bprm_set_security(struct linux_binprm *bprm)
+{
+ /* handle capability bits with setuid, etc */
+ cap_bprm_set_security(bprm);
+ /* already set based on script name */
+ if (bprm->sh_bang)
+ return 0;
+ return aa_register(bprm);
+}
+
+static int apparmor_bprm_secureexec(struct linux_binprm *bprm)
+{
+ int ret = cap_bprm_secureexec(bprm);
+
+ if (!ret && (unsigned long)bprm->security & AA_SECURE_EXEC_NEEDED) {
+ AA_DEBUG("%s: secureexec required for %s\n",
+ __FUNCTION__, bprm->filename);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+static int apparmor_sb_mount(char *dev_name, struct nameidata *nd, char *type,
+ unsigned long flags, void *data)
+{
+ return aa_reject_syscall(current, GFP_KERNEL, "mount");
+}
+
+static int apparmor_umount(struct vfsmount *mnt, int flags)
+{
+ return aa_reject_syscall(current, GFP_KERNEL, "umount");
+}
+
+static int apparmor_inode_mkdir(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt, int mask)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ if (!mnt || !mediated_filesystem(dir))
+ goto out;
+
+ profile = aa_get_profile(current);
+
+ if (profile)
+ error = aa_perm_dir(profile, "inode_mkdir", dentry, mnt,
+ MAY_WRITE);
+
+ aa_put_profile(profile);
+
+out:
+ return error;
+}
+
+static int apparmor_inode_rmdir(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ if (!mnt || !mediated_filesystem(dir))
+ goto out;
+
+ profile = aa_get_profile(current);
+
+ if (profile)
+ error = aa_perm_dir(profile, "inode_rmdir", dentry, mnt,
+ MAY_WRITE);
+
+ aa_put_profile(profile);
+
+out:
+ return error;
+}
+
+static int aa_permission(const char *operation, struct inode *inode,
+ struct dentry *dentry, struct vfsmount *mnt,
+ int mask, int check)
+{
+ int error = 0;
+
+ if (mnt && mediated_filesystem(inode)) {
+ struct aa_profile *profile;
+
+ profile = aa_get_profile(current);
+ if (profile)
+ error = aa_perm(profile, operation, dentry, mnt, mask,
+ check);
+ aa_put_profile(profile);
+ }
+ return error;
+}
+
+static inline int aa_mask_permissions(int mask)
+{
+ if (mask & MAY_APPEND)
+ mask &= (MAY_READ | MAY_APPEND | MAY_EXEC);
+ else
+ mask &= (MAY_READ | MAY_WRITE | MAY_EXEC);
+ return mask;
+}
+
+static int apparmor_inode_create(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt, int mask)
+{
+ return aa_permission("inode_create", dir, dentry, mnt, MAY_APPEND, 0);
+}
+
+static int apparmor_inode_link(struct dentry *old_dentry,
+ struct vfsmount *old_mnt, struct inode *dir,
+ struct dentry *new_dentry,
+ struct vfsmount *new_mnt)
+{
+ int error = 0;
+ struct aa_profile *profile;
+
+ if (!old_mnt || !new_mnt || !mediated_filesystem(dir))
+ goto out;
+
+ profile = aa_get_profile(current);
+
+ if (profile)
+ error = aa_link(profile, new_dentry, new_mnt,
+ old_dentry, old_mnt);
+
+ aa_put_profile(profile);
+
+out:
+ return error;
+}
+
+static int apparmor_inode_unlink(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt)
+{
+ int check = 0;
+
+ if (S_ISDIR(dentry->d_inode->i_mode))
+ check |= AA_CHECK_DIR;
+ return aa_permission("inode_unlink", dir, dentry, mnt, MAY_WRITE,
+ check);
+}
+
+static int apparmor_inode_symlink(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt, const char *old_name)
+{
+ return aa_permission("inode_symlink", dir, dentry, mnt, MAY_WRITE, 0);
+}
+
+static int apparmor_inode_mknod(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt, int mode, dev_t dev)
+{
+ return aa_permission("inode_mknod", dir, dentry, mnt, MAY_WRITE, 0);
+}
+
+static int apparmor_inode_rename(struct inode *old_dir,
+ struct dentry *old_dentry,
+ struct vfsmount *old_mnt,
+ struct inode *new_dir,
+ struct dentry *new_dentry,
+ struct vfsmount *new_mnt)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ if ((!old_mnt && !new_mnt) || !mediated_filesystem(old_dir))
+ goto out;
+
+ profile = aa_get_profile(current);
+
+ if (profile) {
+ struct inode *inode = old_dentry->d_inode;
+ int check = 0;
+
+ if (inode && S_ISDIR(inode->i_mode))
+ check |= AA_CHECK_DIR;
+ if (old_mnt)
+ error = aa_perm(profile, "inode_rename", old_dentry,
+ old_mnt, MAY_READ | MAY_WRITE, check);
+
+ if (!error && new_mnt) {
+ error = aa_perm(profile, "inode_rename", new_dentry,
+ new_mnt, MAY_WRITE, check);
+ }
+ }
+
+ aa_put_profile(profile);
+
+out:
+ return error;
+}
+
+static int apparmor_inode_permission(struct inode *inode, int mask,
+ struct nameidata *nd)
+{
+ int check = 0;
+
+ if (!nd || nd->flags & (LOOKUP_PARENT | LOOKUP_CONTINUE))
+ return 0;
+ mask = aa_mask_permissions(mask);
+ if (S_ISDIR(inode->i_mode)) {
+ check |= AA_CHECK_DIR;
+ /* allow traverse accesses to directories */
+ mask &= ~MAY_EXEC;
+ }
+ return aa_permission("inode_permission", inode, nd->dentry, nd->mnt,
+ mask, check);
+}
+
+static int apparmor_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
+ struct iattr *iattr)
+{
+ int error = 0;
+
+ if (!mnt)
+ goto out;
+
+ if (mediated_filesystem(dentry->d_inode)) {
+ struct aa_profile *profile;
+
+ profile = aa_get_profile(current);
+ /*
+ * Mediate any attempt to change attributes of a file
+ * (chmod, chown, chgrp, etc)
+ */
+ if (profile)
+ error = aa_attr(profile, dentry, mnt, iattr);
+
+ aa_put_profile(profile);
+ }
+
+out:
+ return error;
+}
+
+static int aa_xattr_permission(struct dentry *dentry, struct vfsmount *mnt,
+ const char *operation, int mask,
+ struct file *file)
+{
+ int error = 0;
+
+ if (mnt && mediated_filesystem(dentry->d_inode)) {
+ struct aa_profile *profile = aa_get_profile(current);
+ int check = file ? AA_CHECK_FD : 0;
+
+ if (profile)
+ error = aa_perm_xattr(profile, operation, dentry, mnt,
+ mask, check);
+ aa_put_profile(profile);
+ }
+
+ return error;
+}
+
+static int apparmor_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size,
+ int flags, struct file *file)
+{
+ return aa_xattr_permission(dentry, mnt, "xattr set", MAY_WRITE, file);
+}
+
+static int apparmor_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, struct file *file)
+{
+ return aa_xattr_permission(dentry, mnt, "xattr get", MAY_READ, file);
+}
+
+static int apparmor_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
+ struct file *file)
+{
+ return aa_xattr_permission(dentry, mnt, "xattr list", MAY_READ, file);
+}
+
+static int apparmor_inode_removexattr(struct dentry *dentry,
+ struct vfsmount *mnt, char *name,
+ struct file *file)
+{
+ return aa_xattr_permission(dentry, mnt, "xattr remove", MAY_WRITE,
+ file);
+}
+
+static int aa_file_permission(const char *op, struct file *file, int mask)
+{
+ struct aa_profile *profile;
+ struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
+ int error = 0;
+
+ if (!file_profile)
+ goto out;
+
+ /*
+ * If this file was opened under a different profile, we
+ * revalidate the access against the current profile.
+ */
+ profile = aa_get_profile(current);
+ if (profile && (file_profile != profile || mask & AA_MAY_LOCK)) {
+ struct dentry *dentry = file->f_dentry;
+ struct vfsmount *mnt = file->f_vfsmnt;
+ struct inode *inode = dentry->d_inode;
+ int check = AA_CHECK_FD;
+
+ /*
+ * FIXME: We should remember which profiles we revalidated
+ * against.
+ */
+ if (S_ISDIR(inode->i_mode))
+ check |= AA_CHECK_DIR;
+ error = aa_permission(op, inode, dentry, mnt, mask, check);
+ }
+ aa_put_profile(profile);
+
+out:
+ return error;
+}
+
+static int apparmor_file_permission(struct file *file, int mask)
+{
+ return aa_file_permission("file_permission", file,
+ aa_mask_permissions(mask));
+}
+
+static inline int apparmor_file_lock (struct file *file, unsigned int cmd)
+{
+ int mask = AA_MAY_LOCK;
+ if (cmd == F_WRLCK)
+ mask |= MAY_WRITE;
+ return aa_file_permission("file_lock", file, mask);
+}
+
+static int apparmor_file_alloc_security(struct file *file)
+{
+ struct aa_profile *profile;
+
+ profile = aa_get_profile(current);
+ if (profile)
+ file->f_security = profile;
+
+ return 0;
+}
+
+static void apparmor_file_free_security(struct file *file)
+{
+ struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
+
+ aa_put_profile(file_profile);
+}
+
+static inline int aa_mmap(struct file *file, const char *operation,
+ unsigned long prot, unsigned long flags)
+{
+ struct dentry *dentry;
+ int mask = 0;
+
+ if (!file || !file->f_security)
+ return 0;
+
+ if (prot & PROT_READ)
+ mask |= MAY_READ;
+ /* Private mappings don't require write perms since they don't
+ * write back to the files */
+ if ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE))
+ mask |= MAY_WRITE;
+ if (prot & PROT_EXEC)
+ mask |= AA_EXEC_MMAP;
+
+ dentry = file->f_dentry;
+ return aa_permission(operation, dentry->d_inode, dentry,
+ file->f_vfsmnt, mask, AA_CHECK_FD);
+}
+
+static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
+ unsigned long prot, unsigned long flags,
+ unsigned long addr, unsigned long addr_only)
+{
+ if ((addr < mmap_min_addr) && !capable(CAP_SYS_RAWIO)) {
+ struct aa_profile *profile = aa_get_profile(current);
+ if (profile)
+ /* future control check here */
+ return -EACCES;
+ else
+ return -EACCES;
+ aa_put_profile(profile);
+ }
+
+ return aa_mmap(file, "file_mmap", prot, flags);
+}
+
+static int apparmor_file_mprotect(struct vm_area_struct *vma,
+ unsigned long reqprot, unsigned long prot)
+{
+ return aa_mmap(vma->vm_file, "file_mprotect", prot,
+ !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
+}
+
+static int apparmor_task_alloc_security(struct task_struct *task)
+{
+ return aa_clone(task);
+}
+
+/*
+ * Called from IRQ context from RCU callback.
+ */
+static void apparmor_task_free_security(struct task_struct *task)
+{
+ aa_release(task);
+}
+
+static int apparmor_getprocattr(struct task_struct *task, char *name,
+ char **value)
+{
+ unsigned len;
+ int error;
+ struct aa_profile *profile;
+
+ /* AppArmor only supports the "current" process attribute */
+ if (strcmp(name, "current") != 0)
+ return -EINVAL;
+
+ /* must be task querying itself or admin */
+ if (current != task && !capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ profile = aa_get_profile(task);
+ error = aa_getprocattr(profile, value, &len);
+ aa_put_profile(profile);
+ if (!error)
+ error = len;
+
+ return error;
+}
+
+static int apparmor_setprocattr(struct task_struct *task, char *name,
+ void *value, size_t size)
+{
+ char *command, *args;
+ int error;
+
+ if (strcmp(name, "current") != 0 || size == 0 || size >= PAGE_SIZE)
+ return -EINVAL;
+ args = value;
+ args[size] = '\0';
+ args = strstrip(args);
+ command = strsep(&args, " ");
+ if (!args)
+ return -EINVAL;
+ while (isspace(*args))
+ args++;
+ if (!*args)
+ return -EINVAL;
+
+ if (strcmp(command, "changehat") == 0) {
+ if (current != task)
+ return -EACCES;
+ error = aa_setprocattr_changehat(args);
+ } else if (strcmp(command, "changeprofile") == 0) {
+ if (current != task)
+ return -EACCES;
+ error = aa_setprocattr_changeprofile(args);
+ } else if (strcmp(command, "setprofile") == 0) {
+ struct aa_profile *profile;
+
+ /* Only an unconfined process with admin capabilities
+ * may change the profile of another task.
+ */
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+
+ profile = aa_get_profile(current);
+ if (profile) {
+ struct aa_audit sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.operation = "profile_set";
+ sa.gfp_mask = GFP_KERNEL;
+ sa.task = task->pid;
+ sa.info = "from confined process";
+ aa_audit_reject(profile, &sa);
+ aa_put_profile(profile);
+ return -EACCES;
+ }
+ error = aa_setprocattr_setprofile(task, args);
+ } else {
+ struct aa_audit sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.operation = "setprocattr";
+ sa.gfp_mask = GFP_KERNEL;
+ sa.info = "invalid command";
+ sa.name = command;
+ sa.task = task->pid;
+ aa_audit_reject(NULL, &sa);
+ return -EINVAL;
+ }
+
+ if (!error)
+ error = size;
+ return error;
+}
+
+struct security_operations apparmor_ops = {
+ .ptrace = apparmor_ptrace,
+ .capget = cap_capget,
+ .capset_check = cap_capset_check,
+ .capset_set = cap_capset_set,
+ .sysctl = apparmor_sysctl,
+ .capable = apparmor_capable,
+ .syslog = cap_syslog,
+
+ .netlink_send = cap_netlink_send,
+ .netlink_recv = cap_netlink_recv,
+
+ .bprm_apply_creds = cap_bprm_apply_creds,
+ .bprm_set_security = apparmor_bprm_set_security,
+ .bprm_secureexec = apparmor_bprm_secureexec,
+
+ .sb_mount = apparmor_sb_mount,
+ .sb_umount = apparmor_umount,
+
+ .inode_mkdir = apparmor_inode_mkdir,
+ .inode_rmdir = apparmor_inode_rmdir,
+ .inode_create = apparmor_inode_create,
+ .inode_link = apparmor_inode_link,
+ .inode_unlink = apparmor_inode_unlink,
+ .inode_symlink = apparmor_inode_symlink,
+ .inode_mknod = apparmor_inode_mknod,
+ .inode_rename = apparmor_inode_rename,
+ .inode_permission = apparmor_inode_permission,
+ .inode_setattr = apparmor_inode_setattr,
+ .inode_setxattr = apparmor_inode_setxattr,
+ .inode_getxattr = apparmor_inode_getxattr,
+ .inode_listxattr = apparmor_inode_listxattr,
+ .inode_removexattr = apparmor_inode_removexattr,
+ .file_permission = apparmor_file_permission,
+ .file_alloc_security = apparmor_file_alloc_security,
+ .file_free_security = apparmor_file_free_security,
+ .file_mmap = apparmor_file_mmap,
+ .file_mprotect = apparmor_file_mprotect,
+ .file_lock = apparmor_file_lock,
+
+ .task_alloc_security = apparmor_task_alloc_security,
+ .task_free_security = apparmor_task_free_security,
+ .task_post_setuid = cap_task_post_setuid,
+ .task_reparent_to_init = cap_task_reparent_to_init,
+
+ .getprocattr = apparmor_getprocattr,
+ .setprocattr = apparmor_setprocattr,
+};
+
+void info_message(const char *str)
+{
+ struct aa_audit sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.gfp_mask = GFP_KERNEL;
+ sa.info = str;
+ printk(KERN_INFO "AppArmor: %s\n", str);
+ if (audit_enabled)
+ aa_audit_message(NULL, &sa, AUDIT_APPARMOR_STATUS);
+}
+
+static int __init apparmor_init(void)
+{
+ int error;
+
+ if (!apparmor_enabled) {
+ info_message("AppArmor disabled by boottime parameter\n");
+ return 0;
+ }
+
+ if ((error = create_apparmorfs())) {
+ AA_ERROR("Unable to activate AppArmor filesystem\n");
+ goto createfs_out;
+ }
+
+ if ((error = alloc_default_namespace())){
+ AA_ERROR("Unable to allocate default profile namespace\n");
+ goto alloc_out;
+ }
+
+ if ((error = register_security(&apparmor_ops))) {
+ AA_ERROR("Unable to register AppArmor\n");
+ goto register_security_out;
+ }
+
+ /* Report that AppArmor successfully initialized */
+ apparmor_initialized = 1;
+ if (apparmor_complain)
+ info_message("AppArmor initialized: complainmode enabled");
+ else
+ info_message("AppArmor initialized");
+
+ return error;
+
+register_security_out:
+ free_default_namespace();
+
+alloc_out:
+ destroy_apparmorfs();
+
+createfs_out:
+ return error;
+
+}
+
+security_initcall(apparmor_init);
+
+void apparmor_disable(void)
+{
+ /* Remove and release all the profiles on the profile list. */
+ mutex_lock(&aa_interface_lock);
+ aa_profile_ns_list_release();
+
+ /* FIXME: cleanup profiles references on files */
+ free_default_namespace();
+
+ /*
+ * Delay for an rcu cycle to make sure that all active task
+ * context readers have finished, and all profiles have been
+ * freed by their rcu callbacks.
+ */
+ synchronize_rcu();
+
+ destroy_apparmorfs();
+ mutex_unlock(&aa_interface_lock);
+
+ apparmor_initialized = 0;
+
+ info_message("AppArmor protection removed");
+}
+
+MODULE_DESCRIPTION("AppArmor process confinement");
+MODULE_AUTHOR("Novell/Immunix, http://bugs.opensuse.org");
+MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,408 +0,0 @@
From: John Johansen <jjohansen@suse.de>
Subject: AppArmor: Simplified network controls for AppArmor
Simple network control determining which network families a confined
application has access to.
Signed-off-by: John Johansen <jjohansen@suse.de>
---
security/apparmor/Makefile | 7 +
security/apparmor/apparmor.h | 9 ++
security/apparmor/lsm.c | 129 ++++++++++++++++++++++++++++++++++-
security/apparmor/main.c | 107 ++++++++++++++++++++++++++++-
security/apparmor/module_interface.c | 26 ++++++-
5 files changed, 271 insertions(+), 7 deletions(-)
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -8,6 +8,11 @@ apparmor-y := main.o list.o procattr.o l
quiet_cmd_make-caps = GEN $@
cmd_make-caps = sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z > $@
-$(obj)/main.o : $(obj)/capability_names.h
+quiet_cmd_make-af = GEN $@
+cmd_make-af = sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z > $@
+
+$(obj)/main.o : $(obj)/capability_names.h $(obj)/af_names.h
$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
$(call cmd,make-caps)
+$(obj)/af_names.h : $(srctree)/include/linux/socket.h
+ $(call cmd,make-af)
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -16,6 +16,8 @@
#include <linux/fs.h>
#include <linux/binfmts.h>
#include <linux/rcupdate.h>
+#include <linux/socket.h>
+#include <net/sock.h>
/*
* We use MAY_READ, MAY_WRITE, MAY_EXEC, MAY_APPEND and the following flags
@@ -208,6 +210,9 @@ struct aa_profile {
struct list_head task_contexts;
spinlock_t lock;
unsigned long int_flags;
+ u16 network_families[AF_MAX];
+ u16 audit_network[AF_MAX];
+ u16 quiet_network[AF_MAX];
};
extern struct list_head profile_ns_list;
@@ -254,6 +259,7 @@ struct aa_audit {
int request_mask, denied_mask, audit_mask;
struct iattr *iattr;
pid_t task, parent;
+ int family, type, protocol;
int error_code;
};
@@ -315,6 +321,9 @@ extern void aa_change_task_context(struc
struct aa_profile *previous_profile);
extern int aa_may_ptrace(struct aa_task_context *cxt,
struct aa_profile *tracee);
+extern int aa_net_perm(struct aa_profile *profile, char *operation,
+ int family, int type, int protocol);
+extern int aa_revalidate_sk(struct sock *sk, char *operation);
/* lsm.c */
extern int apparmor_initialized;
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -18,6 +18,7 @@
#include <linux/ctype.h>
#include <linux/sysctl.h>
#include <linux/audit.h>
+#include <net/sock.h>
#include "apparmor.h"
#include "inline.h"
@@ -663,6 +664,117 @@ static void apparmor_task_free_security(
aa_release(task);
}
+static int apparmor_socket_create(int family, int type, int protocol, int kern)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ if (kern)
+ return 0;
+
+ profile = aa_get_profile(current);
+ if (profile)
+ error = aa_net_perm(profile, "socket_create", family,
+ type, protocol);
+ aa_put_profile(profile);
+
+ return error;
+}
+
+static int apparmor_socket_post_create(struct socket *sock, int family,
+ int type, int protocol, int kern)
+{
+ struct sock *sk = sock->sk;
+
+ if (kern)
+ return 0;
+
+ return aa_revalidate_sk(sk, "socket_post_create");
+}
+
+static int apparmor_socket_bind(struct socket *sock,
+ struct sockaddr *address, int addrlen)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_bind");
+}
+
+static int apparmor_socket_connect(struct socket *sock,
+ struct sockaddr *address, int addrlen)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_connect");
+}
+
+static int apparmor_socket_listen(struct socket *sock, int backlog)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_listen");
+}
+
+static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_accept");
+}
+
+static int apparmor_socket_sendmsg(struct socket *sock,
+ struct msghdr *msg, int size)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_sendmsg");
+}
+
+static int apparmor_socket_recvmsg(struct socket *sock,
+ struct msghdr *msg, int size, int flags)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_recvmsg");
+}
+
+static int apparmor_socket_getsockname(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_getsockname");
+}
+
+static int apparmor_socket_getpeername(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_getpeername");
+}
+
+static int apparmor_socket_getsockopt(struct socket *sock, int level,
+ int optname)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_getsockopt");
+}
+
+static int apparmor_socket_setsockopt(struct socket *sock, int level,
+ int optname)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_setsockopt");
+}
+
+static int apparmor_socket_shutdown(struct socket *sock, int how)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(sk, "socket_shutdown");
+}
+
static int apparmor_getprocattr(struct task_struct *task, char *name,
char **value)
{
@@ -763,9 +875,6 @@ struct security_operations apparmor_ops
.capable = apparmor_capable,
.syslog = cap_syslog,
- .netlink_send = cap_netlink_send,
- .netlink_recv = cap_netlink_recv,
-
.bprm_apply_creds = cap_bprm_apply_creds,
.bprm_set_security = apparmor_bprm_set_security,
.bprm_secureexec = apparmor_bprm_secureexec,
@@ -801,6 +910,20 @@ struct security_operations apparmor_ops
.getprocattr = apparmor_getprocattr,
.setprocattr = apparmor_setprocattr,
+
+ .socket_create = apparmor_socket_create,
+ .socket_post_create = apparmor_socket_post_create,
+ .socket_bind = apparmor_socket_bind,
+ .socket_connect = apparmor_socket_connect,
+ .socket_listen = apparmor_socket_listen,
+ .socket_accept = apparmor_socket_accept,
+ .socket_sendmsg = apparmor_socket_sendmsg,
+ .socket_recvmsg = apparmor_socket_recvmsg,
+ .socket_getsockname = apparmor_socket_getsockname,
+ .socket_getpeername = apparmor_socket_getpeername,
+ .socket_getsockopt = apparmor_socket_getsockopt,
+ .socket_setsockopt = apparmor_socket_setsockopt,
+ .socket_shutdown = apparmor_socket_shutdown,
};
void info_message(const char *str)
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -14,6 +14,9 @@
#include <linux/audit.h>
#include <linux/mount.h>
#include <linux/ptrace.h>
+#include <linux/socket.h>
+#include <linux/net.h>
+#include <net/sock.h>
#include "apparmor.h"
@@ -116,6 +119,24 @@ static void aa_audit_file_mask(struct au
audit_log_format(ab, " %s=\"%s::%s\"", name, user, other);
}
+static const char *address_families[] = {
+#include "af_names.h"
+};
+
+static const char *sock_types[] = {
+ "unknown(0)",
+ "stream",
+ "dgram",
+ "raw",
+ "rdm",
+ "seqpacket",
+ "dccp",
+ "unknown(7)",
+ "unknown(8)",
+ "unknown(9)",
+ "packet",
+};
+
/**
* aa_audit - Log an audit event to the audit subsystem
* @profile: profile to check against
@@ -187,7 +208,25 @@ static int aa_audit_base(struct aa_profi
audit_log_untrustedstring(ab, sa->name2);
}
- audit_log_format(ab, " pid=%d", current->pid);
+ if (sa->family || sa->type) {
+ if (address_families[sa->family])
+ audit_log_format(ab, " family=\"%s\"",
+ address_families[sa->family]);
+ else
+ audit_log_format(ab, " family=\"unknown(%d)\"",
+ sa->family);
+
+ if (sock_types[sa->type])
+ audit_log_format(ab, " sock_type=\"%s\"",
+ sock_types[sa->type]);
+ else
+ audit_log_format(ab, " sock_type=\"unknown(%d)\"",
+ sa->type);
+
+ audit_log_format(ab, " protocol=%d", sa->protocol);
+ }
+
+ audit_log_format(ab, " pid=%d", current->pid);
if (profile) {
audit_log_format(ab, " profile=");
@@ -768,6 +807,72 @@ int aa_link(struct aa_profile *profile,
return error;
}
+int aa_net_perm(struct aa_profile *profile, char *operation,
+ int family, int type, int protocol)
+{
+ struct aa_audit sa;
+ int error = 0;
+ u16 family_mask, audit_mask, quiet_mask;
+
+ if ((family < 0) || (family >= AF_MAX))
+ return -EINVAL;
+
+ if ((type < 0) || (type >= SOCK_MAX))
+ return -EINVAL;
+
+ /* unix domain and netlink sockets are handled by ipc */
+ if (family == AF_UNIX || family == AF_NETLINK)
+ return 0;
+
+ family_mask = profile->network_families[family];
+ audit_mask = profile->audit_network[family];
+ quiet_mask = profile->quiet_network[family];
+
+ error = (family_mask & (1 << type)) ? 0 : -EACCES;
+
+ memset(&sa, 0, sizeof(sa));
+ sa.operation = operation;
+ sa.gfp_mask = GFP_KERNEL;
+ sa.family = family;
+ sa.type = type;
+ sa.protocol = protocol;
+ sa.error_code = error;
+
+ if (likely(!error)) {
+ if (!PROFILE_AUDIT(profile) && !(family_mask & audit_mask))
+ return 0;
+ } else if (!((1 << type) & ~quiet_mask)) {
+ return error;
+ }
+
+ error = aa_audit(profile, &sa);
+
+ return error;
+}
+
+int aa_revalidate_sk(struct sock *sk, char *operation)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ /* this is some debugging code to flush out the network hooks that
+ that are called in interrupt context */
+ if (in_interrupt()) {
+ printk("AppArmor Debug: Hook being called from interrupt context\n");
+ dump_stack();
+ return 0;
+ }
+
+ profile = aa_get_profile(current);
+ if (profile)
+ error = aa_net_perm(profile, operation,
+ sk->sk_family, sk->sk_type,
+ sk->sk_protocol);
+ aa_put_profile(profile);
+
+ return error;
+}
+
/*******************************
* Global task related functions
*******************************/
--- a/security/apparmor/module_interface.c
+++ b/security/apparmor/module_interface.c
@@ -320,8 +320,8 @@ static struct aa_profile *aa_unpack_prof
struct aa_audit *sa)
{
struct aa_profile *profile = NULL;
-
- int error = -EPROTO;
+ size_t size = 0;
+ int i, error = -EPROTO;
profile = alloc_aa_profile();
if (!profile)
@@ -354,6 +354,28 @@ static struct aa_profile *aa_unpack_prof
if (!aa_is_u32(e, &(profile->set_caps), NULL))
goto fail;
+ size = aa_is_array(e, "net_allowed_af");
+ if (size) {
+ if (size > AF_MAX)
+ goto fail;
+
+ for (i = 0; i < size; i++) {
+ if (!aa_is_u16(e, &profile->network_families[i], NULL))
+ goto fail;
+ if (!aa_is_u16(e, &profile->audit_network[i], NULL))
+ goto fail;
+ if (!aa_is_u16(e, &profile->quiet_network[i], NULL))
+ goto fail;
+ }
+ if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
+ goto fail;
+ /* allow unix domain and netlink sockets they are handled
+ * by IPC
+ */
+ }
+ profile->network_families[AF_UNIX] = 0xffff;
+ profile->network_families[AF_NETLINK] = 0xffff;
+
/* get file rules */
profile->file_rules = aa_unpack_dfa(e);
if (IS_ERR(profile->file_rules)) {

View File

@@ -1,461 +0,0 @@
From: John Johansen <jjohansen@suse.de>
Subject: AppArmor: per profile controls for system rlimits
Provide contol of rlimits on a per profile basis. Each profile provides
a per limit contol and corresponding hard limit value, such that when a
profile becomes attached to a task it sets the tasks limits to be <= to
the profiles specified limits. Note: the profile limit value will not
raise a tasks limit if it is already less than the profile mandates.
In addition to setting a tasks limits, the ability to set limits on
a confined task are controlled. AppArmor only controls the raising
of a tasks limits Tasks with CAP_SYS_RESOURCE can have their hard limits
raised up to the value specified by the profile. AppArmor does not
prevent a task for lowering its hard limits, nor does it provide
additional control on soft limits.
AppArmor only controls the limits specified in a profile so that
any limit not specified is free to be modified subject to standard
linux limitations.
---
security/apparmor/apparmor.h | 23 ++++++
security/apparmor/apparmorfs.c | 2
security/apparmor/lsm.c | 16 ++++
security/apparmor/main.c | 132 +++++++++++++++++++++++++++++++----
security/apparmor/module_interface.c | 56 ++++++++++++++
5 files changed, 215 insertions(+), 14 deletions(-)
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -16,6 +16,7 @@
#include <linux/fs.h>
#include <linux/binfmts.h>
#include <linux/rcupdate.h>
+#include <linux/resource.h>
#include <linux/socket.h>
#include <net/sock.h>
@@ -136,6 +137,18 @@ extern unsigned int apparmor_path_max;
#define AA_ERROR(fmt, args...) printk(KERN_ERR "AppArmor: " fmt, ##args)
+/* struct aa_rlimit - rlimits settings for the profile
+ * @mask: which hard limits to set
+ * @limits: rlimit values that override task limits
+ *
+ * AppArmor rlimits are used to set confined task rlimits. Only the
+ * limits specified in @mask will be controlled by apparmor.
+ */
+struct aa_rlimit {
+ unsigned int mask;
+ struct rlimit limits[RLIM_NLIMITS];
+};
+
struct aa_profile;
/* struct aa_namespace - namespace for a set of profiles
@@ -170,6 +183,8 @@ struct aa_namespace {
* @audit_caps: caps that are to be audited
* @quiet_caps: caps that should not be audited
* @capabilities: capabilities granted by the process
+ * @rlimits: rlimits for the profile
+ * @task_count: how many tasks the profile is attached to
* @count: reference count of the profile
* @task_contexts: list of tasks confined by profile
* @lock: lock for the task_contexts list
@@ -207,6 +222,9 @@ struct aa_profile {
kernel_cap_t audit_caps;
kernel_cap_t quiet_caps;
+ struct aa_rlimit rlimits;
+ unsigned int task_count;
+
struct kref count;
struct list_head task_contexts;
spinlock_t lock;
@@ -258,6 +276,7 @@ struct aa_audit {
const char *name2;
const char *name3;
int request_mask, denied_mask, audit_mask;
+ int rlimit;
struct iattr *iattr;
pid_t task, parent;
int family, type, protocol;
@@ -325,6 +344,10 @@ extern int aa_may_ptrace(struct aa_task_
extern int aa_net_perm(struct aa_profile *profile, char *operation,
int family, int type, int protocol);
extern int aa_revalidate_sk(struct sock *sk, char *operation);
+extern int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
+ struct rlimit *new_rlim);
+extern void aa_set_rlimits(struct task_struct *task, struct aa_profile *profile);
+
/* lsm.c */
extern int apparmor_initialized;
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -105,7 +105,7 @@ static ssize_t aa_features_read(struct f
{
const char *features = "file=3.0 capability=2.0 network=1.0 "
"change_hat=1.4 change_profile=1.0 "
- "aanamespaces=1.0";
+ "aanamespaces=1.0 rlimit=1.0";
return simple_read_from_buffer(buf, size, ppos, features,
strlen(features));
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -866,6 +866,21 @@ static int apparmor_setprocattr(struct t
return error;
}
+static int apparmor_task_setrlimit(unsigned int resource,
+ struct rlimit *new_rlim)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ profile = aa_get_profile(current);
+ if (profile) {
+ error = aa_task_setrlimit(profile, resource, new_rlim);
+ }
+ aa_put_profile(profile);
+
+ return error;
+}
+
struct security_operations apparmor_ops = {
.ptrace = apparmor_ptrace,
.capget = cap_capget,
@@ -907,6 +922,7 @@ struct security_operations apparmor_ops
.task_free_security = apparmor_task_free_security,
.task_post_setuid = cap_task_post_setuid,
.task_reparent_to_init = cap_task_reparent_to_init,
+ .task_setrlimit = apparmor_task_setrlimit,
.getprocattr = apparmor_getprocattr,
.setprocattr = apparmor_setprocattr,
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -177,6 +177,9 @@ static int aa_audit_base(struct aa_profi
if (sa->request_mask)
audit_log_format(ab, " fsuid=%d", current->fsuid);
+ if (sa->rlimit)
+ audit_log_format(ab, " rlimit=%d", sa->rlimit - 1);
+
if (sa->iattr) {
struct iattr *iattr = sa->iattr;
@@ -872,6 +875,79 @@ int aa_revalidate_sk(struct sock *sk, ch
return error;
}
+/**
+ * aa_task_setrlimit - test permission to set an rlimit
+ * @profile - profile confining the task
+ * @resource - the resource being set
+ * @new_rlim - the new resource limit
+ *
+ * Control raising the processes hard limit.
+ */
+int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
+ struct rlimit *new_rlim)
+{
+ struct aa_audit sa;
+ int error = 0;
+
+ memset(&sa, 0, sizeof(sa));
+ sa.operation = "setrlimit";
+ sa.gfp_mask = GFP_KERNEL;
+ sa.rlimit = resource + 1;
+
+ if (profile->rlimits.mask & (1 << resource) &&
+ new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max) {
+ sa.error_code = -EACCES;
+
+ error = aa_audit(profile, &sa);
+ }
+
+ return error;
+}
+
+static int aa_rlimit_nproc(struct aa_profile *profile) {
+ if (profile && (profile->rlimits.mask & (1 << RLIMIT_NPROC)) &&
+ profile->task_count >= profile->rlimits.limits[RLIMIT_NPROC].rlim_max)
+ return -EAGAIN;
+ return 0;
+}
+
+void aa_set_rlimits(struct task_struct *task, struct aa_profile *profile)
+{
+ int i, mask;
+
+ if (!profile)
+ return;
+
+ if (!profile->rlimits.mask)
+ return;
+
+ task_lock(task->group_leader);
+ mask = 1;
+ for (i = 0; i < RLIM_NLIMITS; i++, mask <<= 1) {
+ struct rlimit new_rlim, *old_rlim;
+
+ /* check to see if NPROC which is per profile and handled
+ * in clone/exec or whether this is a limit to be set
+ * can't set cpu limit either right now
+ */
+ if (i == RLIMIT_NPROC || i == RLIMIT_CPU)
+ continue;
+
+ old_rlim = task->signal->rlim + i;
+ new_rlim = *old_rlim;
+
+ if (mask & profile->rlimits.mask &&
+ profile->rlimits.limits[i].rlim_max < new_rlim.rlim_max) {
+ new_rlim.rlim_max = profile->rlimits.limits[i].rlim_max;
+ /* soft limit should not exceed hard limit */
+ if (new_rlim.rlim_cur > new_rlim.rlim_max)
+ new_rlim.rlim_cur = new_rlim.rlim_max;
+ }
+
+ *old_rlim = new_rlim;
+ }
+ task_unlock(task->group_leader);
+}
/*******************************
* Global task related functions
@@ -885,6 +961,7 @@ int aa_revalidate_sk(struct sock *sk, ch
*/
int aa_clone(struct task_struct *child)
{
+ struct aa_audit sa;
struct aa_task_context *cxt, *child_cxt;
struct aa_profile *profile;
@@ -894,6 +971,11 @@ int aa_clone(struct task_struct *child)
if (!child_cxt)
return -ENOMEM;
+ memset(&sa, 0, sizeof(sa));
+ sa.operation = "clone";
+ sa.task = child->pid;
+ sa.gfp_mask = GFP_KERNEL;
+
repeat:
profile = aa_get_profile(current);
if (profile) {
@@ -910,18 +992,22 @@ repeat:
goto repeat;
}
+ if (aa_rlimit_nproc(profile)) {
+ sa.info = "rlimit nproc limit exceeded";
+ unlock_profile(profile);
+ aa_audit_reject(profile, &sa);
+ aa_put_profile(profile);
+ return -EAGAIN;
+ }
+
/* No need to grab the child's task lock here. */
aa_change_task_context(child, child_cxt, profile,
cxt->cookie, cxt->previous_profile);
+
unlock_profile(profile);
if (APPARMOR_COMPLAIN(child_cxt) &&
profile == profile->ns->null_complain_profile) {
- struct aa_audit sa;
- memset(&sa, 0, sizeof(sa));
- sa.operation = "clone";
- sa.gfp_mask = GFP_KERNEL;
- sa.task = child->pid;
aa_audit_hint(profile, &sa);
}
aa_put_profile(profile);
@@ -1156,6 +1242,10 @@ repeat:
sa.task = current->parent->pid;
aa_audit_reject(profile, &sa);
}
+ if (PTR_ERR(old_profile) == -EAGAIN) {
+ sa.info = "rlimit nproc limit exceeded";
+ aa_audit_reject(profile, &sa);
+ }
new_profile = old_profile;
goto cleanup;
}
@@ -1296,6 +1386,12 @@ static int do_change_profile(struct aa_p
goto out;
}
+ if ((error = aa_rlimit_nproc(new_profile))) {
+ sa->info = "rlimit nproc limit exceeded";
+ aa_audit_reject(cxt->profile, sa);
+ goto out;
+ }
+
if (new_profile == ns->null_complain_profile)
aa_audit_hint(cxt->profile, sa);
@@ -1474,17 +1570,18 @@ struct aa_profile *__aa_replace_profile(
cxt = lock_task_and_profiles(task, profile);
if (unlikely(profile && profile->isstale)) {
- task_unlock(task);
- unlock_both_profiles(profile, cxt ? cxt->profile : NULL);
- aa_free_task_context(new_cxt);
- return ERR_PTR(-ESTALE);
+ old_profile = ERR_PTR(-ESTALE);
+ goto error;
}
if ((current->ptrace & PT_PTRACED) && aa_may_ptrace(cxt, profile)) {
- task_unlock(task);
- unlock_both_profiles(profile, cxt ? cxt->profile : NULL);
- aa_free_task_context(new_cxt);
- return ERR_PTR(-EPERM);
+ old_profile = ERR_PTR(-EPERM);
+ goto error;
+ }
+
+ if (aa_rlimit_nproc(profile)) {
+ old_profile = ERR_PTR(-EAGAIN);
+ goto error;
}
if (cxt)
@@ -1492,8 +1589,15 @@ struct aa_profile *__aa_replace_profile(
aa_change_task_context(task, new_cxt, profile, 0, NULL);
task_unlock(task);
+ aa_set_rlimits(task, profile);
unlock_both_profiles(profile, old_profile);
return old_profile;
+
+error:
+ task_unlock(task);
+ unlock_both_profiles(profile, cxt ? cxt->profile : NULL);
+ aa_free_task_context(new_cxt);
+ return old_profile;
}
/**
@@ -1558,6 +1662,7 @@ void aa_change_task_context(struct task_
if (old_cxt) {
list_del_init(&old_cxt->list);
+ old_cxt->profile->task_count--;
call_rcu(&old_cxt->rcu, free_aa_task_context_rcu_callback);
}
if (new_cxt) {
@@ -1569,6 +1674,7 @@ void aa_change_task_context(struct task_
new_cxt->cookie = cookie;
new_cxt->task = task;
new_cxt->profile = aa_dup_profile(profile);
+ profile->task_count++;
new_cxt->previous_profile = aa_dup_profile(previous_profile);
list_move(&new_cxt->list, &profile->task_contexts);
}
--- a/security/apparmor/module_interface.c
+++ b/security/apparmor/module_interface.c
@@ -177,6 +177,22 @@ fail:
return 0;
}
+static int aa_is_u64(struct aa_ext *e, u64 *data, const char *name)
+{
+ void *pos = e->pos;
+ if (aa_is_nameX(e, AA_U64, name)) {
+ if (!aa_inbounds(e, sizeof(u64)))
+ goto fail;
+ if (data)
+ *data = le64_to_cpu(get_unaligned((u64 *)e->pos));
+ e->pos += sizeof(u64);
+ return 1;
+ }
+fail:
+ e->pos = pos;
+ return 0;
+}
+
static size_t aa_is_array(struct aa_ext *e, const char *name)
{
void *pos = e->pos;
@@ -311,6 +327,39 @@ fail:
return 0;
}
+int aa_unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
+{
+ void *pos = e->pos;
+
+ /* rlimits are optional */
+ if (aa_is_nameX(e, AA_STRUCT, "rlimits")) {
+ int i, size;
+ u32 tmp = 0;
+ if (!aa_is_u32(e, &tmp, NULL))
+ goto fail;
+ profile->rlimits.mask = tmp;
+
+ size = aa_is_array(e, NULL);
+ if (size > RLIM_NLIMITS)
+ goto fail;
+ for (i = 0; i < size; i++) {
+ u64 tmp = 0;
+ if (!aa_is_u64(e, &tmp, NULL))
+ goto fail;
+ profile->rlimits.limits[i].rlim_max = tmp;
+ }
+ if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
+ goto fail;
+ if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
+ goto fail;
+ }
+ return 1;
+
+fail:
+ e->pos = pos;
+ return 0;
+}
+
/**
* aa_unpack_profile - unpack a serialized profile
* @e: serialized data extent information
@@ -354,6 +403,9 @@ static struct aa_profile *aa_unpack_prof
if (!aa_is_u32(e, &(profile->set_caps), NULL))
goto fail;
+ if (!aa_unpack_rlimits(e, profile))
+ goto fail;
+
size = aa_is_array(e, "net_allowed_af");
if (size) {
if (size > AF_MAX)
@@ -613,6 +665,8 @@ ssize_t aa_replace_profile(void *udata,
sa.operation = "profile_load";
goto out;
}
+ /* do not fail replacement based off of profile's NPROC rlimit */
+
/*
* Replacement needs to allocate a new aa_task_context for each
* task confined by old_profile. To do this the profile locks
@@ -633,6 +687,7 @@ ssize_t aa_replace_profile(void *udata,
task_lock(task);
task_replace(task, new_cxt, new_profile);
task_unlock(task);
+ aa_set_rlimits(task, new_profile);
new_cxt = NULL;
}
unlock_both_profiles(old_profile, new_profile);
@@ -655,6 +710,7 @@ out:
*
* remove a profile from the profile list and all aa_task_context references
* to said profile.
+ * NOTE: removing confinement does not restore rlimits to preconfinemnet values
*/
ssize_t aa_remove_profile(char *name, size_t size)
{

View File

@@ -1,212 +0,0 @@
From: John Johnansen <jjohansen@suse.de>
Subject: allow apparmor to stack with dazuko
Patch-mainline: no
References: 300965
Allow AppArmor to stack with dazuko so that the clamav virus
scanner can be used on an AppArmored machine.
Signed-off-by: John Johansen <jjohansen@suse.de>
---
security/apparmor/apparmor.h | 2
security/apparmor/apparmorfs.c | 2
security/apparmor/lsm.c | 101 ++++++++++++++++++++++++++++++++++++-----
3 files changed, 92 insertions(+), 13 deletions(-)
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -347,7 +347,7 @@ extern void aa_set_rlimits(struct task_s
/* lsm.c */
extern int apparmor_initialized;
-extern void info_message(const char *str);
+extern void info_message(const char *str, const char *name);
extern void apparmor_disable(void);
/* list.c */
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -266,7 +266,7 @@ int create_apparmorfs(void)
goto error;
/* Report that AppArmor fs is enabled */
- info_message("AppArmor Filesystem Enabled");
+ info_message("AppArmor Filesystem Enabled", "");
return 0;
error:
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -26,6 +26,20 @@
/* Flag indicating whether initialization completed */
int apparmor_initialized = 0;
+/* point to the apparmor module */
+struct module *aa_module = NULL;
+
+/* secondary ops if apparmor is stacked */
+static struct security_operations *aa_secondary_ops = NULL;
+static DEFINE_MUTEX(aa_secondary_lock);
+
+#define AA_SECONDARY(FN, ARGS...) \
+ ({ \
+ struct security_operations *__f1; \
+ __f1 = rcu_dereference(aa_secondary_ops); \
+ (unlikely(__f1) && __f1->FN) ? __f1->FN(ARGS) : 0; \
+ })
+
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)
@@ -452,19 +466,25 @@ out:
static int apparmor_inode_permission(struct inode *inode, int mask,
struct nameidata *nd)
{
- int check = 0;
+ int check = 0, error = 0;
if (!nd || nd->flags & (LOOKUP_PARENT | LOOKUP_CONTINUE))
- return 0;
+ goto out;
mask = aa_mask_permissions(mask);
if (S_ISDIR(inode->i_mode)) {
check |= AA_CHECK_DIR;
/* allow traverse accesses to directories */
mask &= ~MAY_EXEC;
}
- return aa_permission("inode_permission", inode, nd->path.dentry,
- nd->path.mnt,
- mask, check);
+ error = aa_permission("inode_permission", inode, nd->path.dentry,
+ nd->path.mnt,
+ mask, check);
+
+out:
+ if (!error)
+ error = AA_SECONDARY(inode_permission, inode, mask, nd);
+
+ return error;
}
static int apparmor_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
@@ -882,6 +902,61 @@ static int apparmor_task_setrlimit(unsig
return error;
}
+int apparmor_register_subsecurity(const char *name,
+ struct security_operations *ops)
+{
+ int error = 0;
+
+ if (mutex_lock_interruptible(&aa_secondary_lock))
+ return -ERESTARTSYS;
+
+ /* allow dazuko and capability to stack. The stacking with
+ * capability is not needed since apparmor already composes
+ * capability using common cap.
+ */
+ if (!aa_secondary_ops && (strcmp(name, "dazuko") == 0 ||
+ strcmp(name, "capability") == 0)){
+ /* The apparmor module needs to be pinned while a secondary is
+ * registered
+ */
+ if (try_module_get(aa_module)) {
+ aa_secondary_ops = ops;
+ info_message("Registered secondary security module",
+ name);
+ } else {
+ error = -EINVAL;
+ }
+ } else {
+ info_message("Unable to register %s as a secondary security "
+ "module", name);
+ error = -EPERM;
+ }
+ mutex_unlock(&aa_secondary_lock);
+ return error;
+}
+
+int apparmor_unregister_subsecurity(const char *name,
+ struct security_operations *ops)
+{
+ int error = 0;
+
+ if (mutex_lock_interruptible(&aa_secondary_lock))
+ return -ERESTARTSYS;
+
+ if (aa_secondary_ops && aa_secondary_ops == ops) {
+ rcu_assign_pointer(aa_secondary_ops, NULL);
+ synchronize_rcu();
+ module_put(aa_module);
+ info_message("Unregistered secondary security module", name);
+ } else {
+ info_message("Unable to unregister secondary security module",
+ name);
+ error = -EPERM;
+ }
+ mutex_unlock(&aa_secondary_lock);
+ return error;
+}
+
struct security_operations apparmor_ops = {
.ptrace = apparmor_ptrace,
.capget = cap_capget,
@@ -928,6 +1003,8 @@ struct security_operations apparmor_ops
.getprocattr = apparmor_getprocattr,
.setprocattr = apparmor_setprocattr,
+ .register_security = apparmor_register_subsecurity,
+
.socket_create = apparmor_socket_create,
.socket_post_create = apparmor_socket_post_create,
.socket_bind = apparmor_socket_bind,
@@ -943,13 +1020,14 @@ struct security_operations apparmor_ops
.socket_shutdown = apparmor_socket_shutdown,
};
-void info_message(const char *str)
+void info_message(const char *str, const char *name)
{
struct aa_audit sa;
memset(&sa, 0, sizeof(sa));
sa.gfp_mask = GFP_KERNEL;
sa.info = str;
- printk(KERN_INFO "AppArmor: %s\n", str);
+ sa.name = name;
+ printk(KERN_INFO "AppArmor: %s %s\n", str, name);
if (audit_enabled)
aa_audit_message(NULL, &sa, AUDIT_APPARMOR_STATUS);
}
@@ -959,7 +1037,7 @@ static int __init apparmor_init(void)
int error;
if (!apparmor_enabled) {
- info_message("AppArmor disabled by boottime parameter\n");
+ info_message("AppArmor disabled by boottime parameter", "");
return 0;
}
@@ -981,9 +1059,10 @@ static int __init apparmor_init(void)
/* Report that AppArmor successfully initialized */
apparmor_initialized = 1;
if (apparmor_complain)
- info_message("AppArmor initialized: complainmode enabled");
+ info_message("AppArmor initialized: complainmode enabled",
+ NULL);
else
- info_message("AppArmor initialized");
+ info_message("AppArmor initialized", NULL);
return error;
@@ -1021,7 +1100,7 @@ void apparmor_disable(void)
apparmor_initialized = 0;
- info_message("AppArmor protection removed");
+ info_message("AppArmor protection removed", NULL);
}
MODULE_DESCRIPTION("AppArmor process confinement");

View File

@@ -1,87 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Add d_namespace_path() to compute namespace relative pathnames
In AppArmor, we are interested in pathnames relative to the namespace root.
This is the same as d_path() except for the root where the search ends. Add
a function for computing the namespace-relative path.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/dcache.c | 6 +++---
fs/namespace.c | 27 +++++++++++++++++++++++++++
include/linux/dcache.h | 3 ++-
include/linux/mount.h | 2 ++
4 files changed, 34 insertions(+), 4 deletions(-)
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1766,9 +1766,9 @@ shouldnt_be_hashed:
*
* Returns the buffer or an error code.
*/
-static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
- struct path *root, char *buffer, int buflen,
- int fail_deleted)
+char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
+ struct path *root, char *buffer, int buflen,
+ int fail_deleted)
{
int namelen, is_slash, vfsmount_locked = 0;
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1852,3 +1852,30 @@ void __put_mnt_ns(struct mnt_namespace *
release_mounts(&umount_list);
kfree(ns);
}
+
+char *d_namespace_path(struct dentry *dentry, struct vfsmount *vfsmnt,
+ char *buf, int buflen)
+{
+ struct path root, ns_root = { };
+ char *res;
+
+ read_lock(&current->fs->lock);
+ root = current->fs->root;
+ path_get(&current->fs->root);
+ read_unlock(&current->fs->lock);
+ spin_lock(&vfsmount_lock);
+ if (root.mnt)
+ ns_root.mnt = mntget(root.mnt->mnt_ns->root);
+ if (ns_root.mnt)
+ ns_root.dentry = dget(ns_root.mnt->mnt_root);
+ spin_unlock(&vfsmount_lock);
+ res = __d_path(dentry, vfsmnt, &ns_root, buf, buflen, 1);
+ path_put(&root);
+ path_put(&ns_root);
+
+ /* Prevent empty path for lazily unmounted filesystems. */
+ if (!IS_ERR(res) && *res == '\0')
+ *--res = '.';
+ return res;
+}
+EXPORT_SYMBOL(d_namespace_path);
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -300,7 +300,8 @@ extern int d_validate(struct dentry *, s
* helper function for dentry_operations.d_dname() members
*/
extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
-
+extern char *__d_path(struct dentry *, struct vfsmount *, struct path *,
+ char *, int, int);
extern char *d_path(struct path *, char *, int);
/* Allocation counts.. */
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -103,5 +103,7 @@ extern void mark_mounts_for_expiry(struc
extern spinlock_t vfsmount_lock;
extern dev_t name_to_dev_t(char *name);
+extern char *d_namespace_path(struct dentry *, struct vfsmount *, char *, int);
+
#endif
#endif /* _LINUX_MOUNT_H */

View File

@@ -1,42 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Switch to vfs_permission() in do_path_lookup()
Switch from file_permission() to vfs_permission() in do_path_lookup():
this avoids calling permission() with a NULL nameidata here.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1150,24 +1150,21 @@ static int do_path_lookup(int dfd, const
path_get(&fs->pwd);
read_unlock(&fs->lock);
} else {
- struct dentry *dentry;
-
file = fget_light(dfd, &fput_needed);
retval = -EBADF;
if (!file)
goto out_fail;
- dentry = file->f_path.dentry;
+ nd->path = file->f_path;
retval = -ENOTDIR;
- if (!S_ISDIR(dentry->d_inode->i_mode))
+ if (!S_ISDIR(nd->path.dentry->d_inode->i_mode))
goto fput_fail;
retval = file_permission(file, MAY_EXEC);
if (retval)
goto fput_fail;
- nd->path = file->f_path;
path_get(&file->f_path);
fput_light(file, fput_needed);

View File

@@ -1,84 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Enable LSM hooks to distinguish operations on file descriptors from operations on pathnames
Struct iattr already contains ia_file since commit cc4e69de from
Miklos (which is related to commit befc649c). Use this to pass
struct file down the setattr hooks. This allows LSMs to distinguish
operations on file descriptors from operations on paths.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
Cc: Miklos Szeredi <mszeredi@suse.cz>
---
fs/nfsd/vfs.c | 12 +++++++-----
fs/open.c | 5 ++++-
2 files changed, 11 insertions(+), 6 deletions(-)
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -413,7 +413,7 @@ static ssize_t nfsd_getxattr(struct dent
{
ssize_t buflen;
- buflen = vfs_getxattr(dentry, mnt, key, NULL, 0);
+ buflen = vfs_getxattr(dentry, mnt, key, NULL, 0, NULL);
if (buflen <= 0)
return buflen;
@@ -421,7 +421,7 @@ static ssize_t nfsd_getxattr(struct dent
if (!*buf)
return -ENOMEM;
- return vfs_getxattr(dentry, mnt, key, *buf, buflen);
+ return vfs_getxattr(dentry, mnt, key, *buf, buflen, NULL);
}
#endif
@@ -447,7 +447,7 @@ set_nfsv4_acl_one(struct dentry *dentry,
goto out;
}
- error = vfs_setxattr(dentry, mnt, key, buf, len, 0);
+ error = vfs_setxattr(dentry, mnt, key, buf, len, 0, NULL);
out:
kfree(buf);
return error;
@@ -2061,12 +2061,14 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i
mnt = fhp->fh_export->ex_path.mnt;
if (size)
- error = vfs_setxattr(fhp->fh_dentry, mnt, name, value, size,0);
+ error = vfs_setxattr(fhp->fh_dentry, mnt, name, value, size, 0,
+ NULL);
else {
if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
error = 0;
else {
- error = vfs_removexattr(fhp->fh_dentry, mnt, name);
+ error = vfs_removexattr(fhp->fh_dentry, mnt, name,
+ NULL);
if (error == -ENODATA)
error = 0;
}
--- a/fs/open.c
+++ b/fs/open.c
@@ -577,7 +577,7 @@ asmlinkage long sys_fchmod(unsigned int
if (mode == (mode_t) -1)
mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
- newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+ newattrs.ia_valid = ATTR_MODE | ATTR_CTIME | ATTR_FILE;
err = fnotify_change(dentry, file->f_path.mnt, &newattrs, file);
mutex_unlock(&inode->i_mutex);
@@ -657,6 +657,9 @@ static int chown_common(struct dentry *
if (!S_ISDIR(inode->i_mode))
newattrs.ia_valid |=
ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
+ if (file)
+ newattrs.ia_valid |= ATTR_FILE;
+
mutex_lock(&inode->i_mutex);
error = fnotify_change(dentry, mnt, &newattrs, file);
mutex_unlock(&inode->i_mutex);

View File

@@ -1,30 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Fix file_permission()
We cannot easily switch from file_permission() to vfs_permission()
everywhere, so fix file_permission() to not use a NULL nameidata
for the remaining users.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -313,7 +313,12 @@ int vfs_permission(struct nameidata *nd,
*/
int file_permission(struct file *file, int mask)
{
- return permission(file->f_path.dentry->d_inode, mask, NULL);
+ struct nameidata nd;
+
+ nd.path = file->f_path;
+ nd.flags = LOOKUP_ACCESS;
+
+ return permission(nd.path.dentry->d_inode, mask, &nd);
}
/*

View File

@@ -1,44 +0,0 @@
From: John Johansen <jjohansen@suse.de>
Subject: 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 <jjohansen@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
fs/namei.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2100,6 +2100,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);
@@ -2107,12 +2111,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) {

View File

@@ -1,39 +0,0 @@
From: John Johansen <jjohansen@suse.de>
Subject: AppArmor: reintroduce ATTR_FILE
The fsetattr patch removed ATTR_FILE but AppArmor needs it to distinguish
file based writes.
Note: Now that LSMs must be static, it would be better to add a file
pointer argument to security_operations->inode_setattr() instead. Then
move the fs.h chunk to patches.apparmor/fsetattr-restore-ia_file. -jeffm
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/open.c | 3 +++
include/linux/fs.h | 1 +
2 files changed, 4 insertions(+)
--- a/fs/open.c
+++ b/fs/open.c
@@ -207,6 +207,9 @@ int do_truncate(struct dentry *dentry, s
newattrs.ia_size = length;
newattrs.ia_valid = ATTR_SIZE | time_attrs;
+ if (filp)
+ newattrs.ia_valid |= ATTR_FILE;
+
/* Remove suid/sgid on truncate too */
newattrs.ia_valid |= should_remove_suid(dentry);
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -331,6 +331,7 @@ typedef void (dio_iodone_t)(struct kiocb
#define ATTR_ATTR_FLAG 1024
#define ATTR_KILL_SUID 2048
#define ATTR_KILL_SGID 4096
+#define ATTR_FILE 8192
#define ATTR_KILL_PRIV 16384
#define ATTR_OPEN 32768 /* Truncating from open(O_TRUNC) */

View File

@@ -1,394 +0,0 @@
Subject: VFS: new fsetattr() file operation
From: Miklos Szeredi <mszeredi@suse.cz>
Add a new file operation: f_op->fsetattr(), that is invoked by
ftruncate, fchmod, fchown and utimensat. Fall back to i_op->setattr()
if it is not defined.
For the reasons why we need this, see patch adding fgetattr().
ftruncate() already passed the open file to the filesystem via the
ia_file member of struct iattr. However it is cleaner to have a
separate file operation for this, so remove ia_file, ATTR_FILE and
convert existing users: fuse and AFS.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> ---
Signed-off-by: John Johansen <jjohansen@suse.de> ---
---
fs/afs/dir.c | 1 +
fs/afs/file.c | 1 +
fs/afs/inode.c | 19 +++++++++++++++----
fs/afs/internal.h | 1 +
fs/attr.c | 19 +++++++++++++++----
fs/fuse/dir.c | 20 +++++++++-----------
fs/fuse/file.c | 7 +++++++
fs/fuse/fuse_i.h | 4 ++++
fs/open.c | 20 ++++++++------------
fs/utimes.c | 2 +-
include/linux/fs.h | 10 ++--------
11 files changed, 64 insertions(+), 40 deletions(-)
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -45,6 +45,7 @@ const struct file_operations afs_dir_fil
.release = afs_release,
.readdir = afs_readdir,
.lock = afs_lock,
+ .fsetattr = afs_fsetattr,
};
const struct inode_operations afs_dir_inode_operations = {
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -36,6 +36,7 @@ const struct file_operations afs_file_op
.fsync = afs_fsync,
.lock = afs_lock,
.flock = afs_flock,
+ .fsetattr = afs_fsetattr,
};
const struct inode_operations afs_file_inode_operations = {
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -358,7 +358,8 @@ void afs_clear_inode(struct inode *inode
/*
* set the attributes of an inode
*/
-int afs_setattr(struct dentry *dentry, struct iattr *attr)
+static int afs_do_setattr(struct dentry *dentry, struct iattr *attr,
+ struct file *file)
{
struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
struct key *key;
@@ -380,8 +381,8 @@ int afs_setattr(struct dentry *dentry, s
afs_writeback_all(vnode);
}
- if (attr->ia_valid & ATTR_FILE) {
- key = attr->ia_file->private_data;
+ if (file) {
+ key = file->private_data;
} else {
key = afs_request_key(vnode->volume->cell);
if (IS_ERR(key)) {
@@ -391,10 +392,20 @@ int afs_setattr(struct dentry *dentry, s
}
ret = afs_vnode_setattr(vnode, key, attr);
- if (!(attr->ia_valid & ATTR_FILE))
+ if (!file)
key_put(key);
error:
_leave(" = %d", ret);
return ret;
}
+
+int afs_setattr(struct dentry *dentry, struct iattr *attr)
+{
+ return afs_do_setattr(dentry, attr, NULL);
+}
+
+int afs_fsetattr(struct file *file, struct iattr *attr)
+{
+ return afs_do_setattr(file->f_path.dentry, attr, file);
+}
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -550,6 +550,7 @@ extern void afs_zap_data(struct afs_vnod
extern int afs_validate(struct afs_vnode *, struct key *);
extern int afs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
extern int afs_setattr(struct dentry *, struct iattr *);
+extern int afs_fsetattr(struct file *, struct iattr *);
extern void afs_clear_inode(struct inode *);
/*
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -100,8 +100,8 @@ int inode_setattr(struct inode * inode,
}
EXPORT_SYMBOL(inode_setattr);
-int notify_change(struct dentry *dentry, struct vfsmount *mnt,
- struct iattr *attr)
+int fnotify_change(struct dentry *dentry, struct vfsmount *mnt,
+ struct iattr *attr, struct file *file)
{
struct inode *inode = dentry->d_inode;
mode_t mode = inode->i_mode;
@@ -160,8 +160,12 @@ int notify_change(struct dentry *dentry,
if (inode->i_op && inode->i_op->setattr) {
error = security_inode_setattr(dentry, mnt, attr);
- if (!error)
- error = inode->i_op->setattr(dentry, attr);
+ if (!error) {
+ if (file && file->f_op && file->f_op->fsetattr)
+ error = file->f_op->fsetattr(file, attr);
+ else
+ error = inode->i_op->setattr(dentry, attr);
+ }
} else {
error = inode_change_ok(inode, attr);
if (!error)
@@ -183,5 +187,12 @@ int notify_change(struct dentry *dentry,
return error;
}
+EXPORT_SYMBOL_GPL(fnotify_change);
+
+int notify_change(struct dentry *dentry, struct vfsmount *mnt,
+ struct iattr *attr)
+{
+ return fnotify_change(dentry, mnt, attr, NULL);
+}
EXPORT_SYMBOL(notify_change);
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1064,21 +1064,22 @@ static int fuse_dir_fsync(struct file *f
return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
}
-static bool update_mtime(unsigned ivalid)
+static bool update_mtime(unsigned ivalid, bool have_file)
{
/* Always update if mtime is explicitly set */
if (ivalid & ATTR_MTIME_SET)
return true;
/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
- if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
+ if ((ivalid & ATTR_SIZE) && ((ivalid & ATTR_OPEN) || have_file))
return false;
/* In all other cases update */
return true;
}
-static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
+static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg,
+ bool have_file)
{
unsigned ivalid = iattr->ia_valid;
@@ -1097,7 +1098,7 @@ static void iattr_to_fattr(struct iattr
if (!(ivalid & ATTR_ATIME_SET))
arg->valid |= FATTR_ATIME_NOW;
}
- if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
+ if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, have_file)) {
arg->valid |= FATTR_MTIME;
arg->mtime = iattr->ia_mtime.tv_sec;
arg->mtimensec = iattr->ia_mtime.tv_nsec;
@@ -1114,8 +1115,8 @@ static void iattr_to_fattr(struct iattr
* vmtruncate() doesn't allow for this case, so do the rlimit checking
* and the actual truncation by hand.
*/
-static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
- struct file *file)
+int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
+ struct file *file)
{
struct inode *inode = entry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
@@ -1153,7 +1154,7 @@ static int fuse_do_setattr(struct dentry
memset(&inarg, 0, sizeof(inarg));
memset(&outarg, 0, sizeof(outarg));
- iattr_to_fattr(attr, &inarg);
+ iattr_to_fattr(attr, &inarg, file != NULL);
if (file) {
struct fuse_file *ff = file->private_data;
inarg.valid |= FATTR_FH;
@@ -1195,10 +1196,7 @@ static int fuse_do_setattr(struct dentry
static int fuse_setattr(struct dentry *entry, struct iattr *attr)
{
- if (attr->ia_valid & ATTR_FILE)
- return fuse_do_setattr(entry, attr, attr->ia_file);
- else
- return fuse_do_setattr(entry, attr, NULL);
+ return fuse_do_setattr(entry, attr, NULL);
}
static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -909,6 +909,11 @@ static sector_t fuse_bmap(struct address
return err ? 0 : outarg.block;
}
+static int fuse_fsetattr(struct file *file, struct iattr *attr)
+{
+ return fuse_do_setattr(file->f_path.dentry, attr, file);
+}
+
static const struct file_operations fuse_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
@@ -922,6 +927,7 @@ static const struct file_operations fuse
.fsync = fuse_fsync,
.lock = fuse_file_lock,
.flock = fuse_file_flock,
+ .fsetattr = fuse_fsetattr,
.splice_read = generic_file_splice_read,
};
@@ -935,6 +941,7 @@ static const struct file_operations fuse
.fsync = fuse_fsync,
.lock = fuse_file_lock,
.flock = fuse_file_flock,
+ .fsetattr = fuse_fsetattr,
/* no mmap and splice_read */
};
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -509,6 +509,10 @@ void fuse_change_attributes(struct inode
*/
int fuse_dev_init(void);
+
+int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
+ struct file *file);
+
/**
* Cleanup the client device
*/
--- a/fs/open.c
+++ b/fs/open.c
@@ -206,16 +206,12 @@ int do_truncate(struct dentry *dentry, s
newattrs.ia_size = length;
newattrs.ia_valid = ATTR_SIZE | time_attrs;
- if (filp) {
- newattrs.ia_file = filp;
- newattrs.ia_valid |= ATTR_FILE;
- }
/* Remove suid/sgid on truncate too */
newattrs.ia_valid |= should_remove_suid(dentry);
mutex_lock(&dentry->d_inode->i_mutex);
- err = notify_change(dentry, mnt, &newattrs);
+ err = fnotify_change(dentry, mnt, &newattrs, filp);
mutex_unlock(&dentry->d_inode->i_mutex);
return err;
}
@@ -579,7 +575,7 @@ asmlinkage long sys_fchmod(unsigned int
mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
- err = notify_change(dentry, file->f_path.mnt, &newattrs);
+ err = fnotify_change(dentry, file->f_path.mnt, &newattrs, file);
mutex_unlock(&inode->i_mutex);
out_putf:
@@ -629,7 +625,7 @@ asmlinkage long sys_chmod(const char __u
}
static int chown_common(struct dentry * dentry, struct vfsmount *mnt,
- uid_t user, gid_t group)
+ uid_t user, gid_t group, struct file *file)
{
struct inode * inode;
int error;
@@ -659,7 +655,7 @@ static int chown_common(struct dentry *
newattrs.ia_valid |=
ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
mutex_lock(&inode->i_mutex);
- error = notify_change(dentry, mnt, &newattrs);
+ error = fnotify_change(dentry, mnt, &newattrs, file);
mutex_unlock(&inode->i_mutex);
out:
return error;
@@ -673,7 +669,7 @@ asmlinkage long sys_chown(const char __u
error = user_path_walk(filename, &nd);
if (error)
goto out;
- error = chown_common(nd.path.dentry, nd.path.mnt, user, group);
+ error = chown_common(nd.path.dentry, nd.path.mnt, user, group, NULL);
path_put(&nd.path);
out:
return error;
@@ -693,7 +689,7 @@ asmlinkage long sys_fchownat(int dfd, co
error = __user_walk_fd(dfd, filename, follow, &nd);
if (error)
goto out;
- error = chown_common(nd.path.dentry, nd.path.mnt, user, group);
+ error = chown_common(nd.path.dentry, nd.path.mnt, user, group, NULL);
path_put(&nd.path);
out:
return error;
@@ -707,7 +703,7 @@ asmlinkage long sys_lchown(const char __
error = user_path_walk_link(filename, &nd);
if (error)
goto out;
- error = chown_common(nd.path.dentry, nd.path.mnt, user, group);
+ error = chown_common(nd.path.dentry, nd.path.mnt, user, group, NULL);
path_put(&nd.path);
out:
return error;
@@ -726,7 +722,7 @@ asmlinkage long sys_fchown(unsigned int
dentry = file->f_path.dentry;
audit_inode(NULL, dentry);
- error = chown_common(dentry, file->f_path.mnt, user, group);
+ error = chown_common(dentry, file->f_path.mnt, user, group, file);
fput(file);
out:
return error;
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -132,7 +132,7 @@ long do_utimes(int dfd, char __user *fil
}
}
mutex_lock(&inode->i_mutex);
- error = notify_change(path.dentry, path.mnt, &newattrs);
+ error = fnotify_change(path.dentry, path.mnt, &newattrs, f);
mutex_unlock(&inode->i_mutex);
dput_and_out:
if (f)
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -331,7 +331,6 @@ typedef void (dio_iodone_t)(struct kiocb
#define ATTR_ATTR_FLAG 1024
#define ATTR_KILL_SUID 2048
#define ATTR_KILL_SGID 4096
-#define ATTR_FILE 8192
#define ATTR_KILL_PRIV 16384
#define ATTR_OPEN 32768 /* Truncating from open(O_TRUNC) */
@@ -353,13 +352,6 @@ struct iattr {
struct timespec ia_atime;
struct timespec ia_mtime;
struct timespec ia_ctime;
-
- /*
- * Not an attribute, but an auxilary info for filesystems wanting to
- * implement an ftruncate() like method. NOTE: filesystem should
- * check for (ia_valid & ATTR_FILE), and not for (ia_file != NULL).
- */
- struct file *ia_file;
};
/*
@@ -1196,6 +1188,7 @@ struct file_operations {
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
int (*setlease)(struct file *, long, struct file_lock **);
+ int (*fsetattr)(struct file *, struct iattr *);
};
struct inode_operations {
@@ -1715,6 +1708,7 @@ extern int do_remount_sb(struct super_bl
extern sector_t bmap(struct inode *, sector_t);
#endif
extern int notify_change(struct dentry *, struct vfsmount *, struct iattr *);
+extern int fnotify_change(struct dentry *, struct vfsmount *, struct iattr *, struct file *);
extern int permission(struct inode *, int, struct nameidata *);
extern int generic_permission(struct inode *, int,
int (*check_acl)(struct inode *, int));

View File

@@ -1,60 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Make d_path() consistent across mount operations
The path that __d_path() computes can become slightly inconsistent when it
races with mount operations: it grabs the vfsmount_lock when traversing mount
points but immediately drops it again, only to re-grab it when it reaches the
next mount point. The result is that the filename computed is not always
consisent, and the file may never have had that name. (This is unlikely, but
still possible.)
Fix this by grabbing the vfsmount_lock when the first mount point is reached,
and holding onto it until the d_cache lookup is completed.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/dcache.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1770,7 +1770,7 @@ static char *__d_path(struct dentry *den
struct path *root, char *buffer, int buflen,
int fail_deleted)
{
- int namelen, is_slash;
+ int namelen, is_slash, vfsmount_locked = 0;
if (buflen < 2)
return ERR_PTR(-ENAMETOOLONG);
@@ -1794,14 +1794,14 @@ static char *__d_path(struct dentry *den
struct dentry * parent;
if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
- spin_lock(&vfsmount_lock);
- if (vfsmnt->mnt_parent == vfsmnt) {
- spin_unlock(&vfsmount_lock);
- goto global_root;
+ if (!vfsmount_locked) {
+ spin_lock(&vfsmount_lock);
+ vfsmount_locked = 1;
}
+ if (vfsmnt->mnt_parent == vfsmnt)
+ goto global_root;
dentry = vfsmnt->mnt_mountpoint;
vfsmnt = vfsmnt->mnt_parent;
- spin_unlock(&vfsmount_lock);
continue;
}
parent = dentry->d_parent;
@@ -1820,6 +1820,8 @@ static char *__d_path(struct dentry *den
*--buffer = '/';
out:
+ if (vfsmount_locked)
+ spin_unlock(&vfsmount_lock);
spin_unlock(&dcache_lock);
return buffer;

View File

@@ -1,24 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Allow permission functions to tell between parent and leaf checks
Set the LOOKUP_CONTINUE flag when checking parent permissions. This allows
permission functions to tell between parent and leaf checks.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 2 ++
1 file changed, 2 insertions(+)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1511,6 +1511,8 @@ static inline int may_create(struct inod
return -EEXIST;
if (IS_DEADDIR(dir))
return -ENOENT;
+ if (nd)
+ nd->flags |= LOOKUP_CONTINUE;
return permission(dir,MAY_WRITE | MAY_EXEC, nd);
}

View File

@@ -1,132 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Pass struct path down to remove_suid and children
Required by a later patch that adds a struct vfsmount parameter to
notify_change().
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/ntfs/file.c | 2 +-
fs/splice.c | 4 ++--
fs/xfs/linux-2.6/xfs_lrw.c | 2 +-
include/linux/fs.h | 4 ++--
mm/filemap.c | 16 ++++++++--------
mm/filemap_xip.c | 2 +-
6 files changed, 15 insertions(+), 15 deletions(-)
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -2118,7 +2118,7 @@ static ssize_t ntfs_file_aio_write_noloc
goto out;
if (!count)
goto out;
- err = remove_suid(file->f_path.dentry);
+ err = remove_suid(&file->f_path);
if (err)
goto out;
file_update_time(file);
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -781,7 +781,7 @@ generic_file_splice_write_nolock(struct
ssize_t ret;
int err;
- err = remove_suid(out->f_path.dentry);
+ err = remove_suid(&out->f_path);
if (unlikely(err))
return err;
@@ -841,7 +841,7 @@ generic_file_splice_write(struct pipe_in
if (killpriv)
err = security_inode_killpriv(out->f_path.dentry);
if (!err && killsuid)
- err = __remove_suid(out->f_path.dentry, killsuid);
+ err = __remove_suid(&out->f_path, killsuid);
mutex_unlock(&inode->i_mutex);
if (err)
return err;
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -716,7 +716,7 @@ start:
!capable(CAP_FSETID)) {
error = xfs_write_clear_setuid(xip);
if (likely(!error))
- error = -remove_suid(file->f_path.dentry);
+ error = -remove_suid(&file->f_path);
if (unlikely(error)) {
goto out_unlock_internal;
}
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1776,9 +1776,9 @@ extern void iget_failed(struct inode *);
extern void clear_inode(struct inode *);
extern void destroy_inode(struct inode *);
extern struct inode *new_inode(struct super_block *);
-extern int __remove_suid(struct dentry *, int);
+extern int __remove_suid(struct path *, int);
extern int should_remove_suid(struct dentry *);
-extern int remove_suid(struct dentry *);
+extern int remove_suid(struct path *);
extern void __insert_inode_hash(struct inode *, unsigned long hashval);
extern void remove_inode_hash(struct inode *);
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1653,26 +1653,26 @@ int should_remove_suid(struct dentry *de
}
EXPORT_SYMBOL(should_remove_suid);
-int __remove_suid(struct dentry *dentry, int kill)
+int __remove_suid(struct path *path, int kill)
{
struct iattr newattrs;
newattrs.ia_valid = ATTR_FORCE | kill;
- return notify_change(dentry, &newattrs);
+ return notify_change(path->dentry, &newattrs);
}
-int remove_suid(struct dentry *dentry)
+int remove_suid(struct path *path)
{
- int killsuid = should_remove_suid(dentry);
- int killpriv = security_inode_need_killpriv(dentry);
+ int killsuid = should_remove_suid(path->dentry);
+ int killpriv = security_inode_need_killpriv(path->dentry);
int error = 0;
if (killpriv < 0)
return killpriv;
if (killpriv)
- error = security_inode_killpriv(dentry);
+ error = security_inode_killpriv(path->dentry);
if (!error && killsuid)
- error = __remove_suid(dentry, killsuid);
+ error = __remove_suid(path, killsuid);
return error;
}
@@ -2387,7 +2387,7 @@ __generic_file_aio_write_nolock(struct k
if (count == 0)
goto out;
- err = remove_suid(file->f_path.dentry);
+ err = remove_suid(&file->f_path);
if (err)
goto out;
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -380,7 +380,7 @@ xip_file_write(struct file *filp, const
if (count == 0)
goto out_backing;
- ret = remove_suid(filp->f_path.dentry);
+ ret = remove_suid(&filp->f_path);
if (ret)
goto out_backing;

View File

@@ -1,107 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_create LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 2 +-
include/linux/security.h | 9 ++++++---
security/dummy.c | 2 +-
security/security.c | 5 +++--
security/selinux/hooks.c | 3 ++-
5 files changed, 13 insertions(+), 8 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1586,7 +1586,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->path.mnt : NULL, mode);
if (error)
return error;
DQUOT_INIT(dir);
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -330,6 +330,7 @@ static inline void security_free_mnt_opt
* 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:
@@ -1286,8 +1287,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);
@@ -1549,7 +1550,8 @@ int security_inode_alloc(struct inode *i
void security_inode_free(struct inode *inode);
int security_inode_init_security(struct inode *inode, struct inode *dir,
char **name, void **value, size_t *len);
-int security_inode_create(struct inode *dir, struct dentry *dentry, int mode);
+int security_inode_create(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt, int mode);
int security_inode_link(struct dentry *old_dentry, struct inode *dir,
struct dentry *new_dentry);
int security_inode_unlink(struct inode *dir, struct dentry *dentry);
@@ -1887,6 +1889,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
@@ -287,7 +287,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/security.c
+++ b/security/security.c
@@ -352,11 +352,12 @@ int security_inode_init_security(struct
}
EXPORT_SYMBOL(security_inode_init_security);
-int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
+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);
}
int security_inode_link(struct dentry *old_dentry, struct inode *dir,
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2448,7 +2448,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);
}

View File

@@ -1,110 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_getxattr LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/xattr.c | 2 +-
include/linux/security.h | 11 +++++++----
security/dummy.c | 3 ++-
security/security.c | 5 +++--
security/selinux/hooks.c | 3 ++-
5 files changed, 15 insertions(+), 9 deletions(-)
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -142,7 +142,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
@@ -438,7 +438,7 @@ static inline void security_free_mnt_opt
* @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
@@ -1330,7 +1330,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);
int (*inode_need_killpriv) (struct dentry *dentry);
@@ -1600,7 +1601,8 @@ int security_inode_setxattr(struct dentr
void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
char *name, void *value, size_t size,
int flags);
-int security_inode_getxattr(struct dentry *dentry, char *name);
+int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name);
int security_inode_listxattr(struct dentry *dentry);
int security_inode_removexattr(struct dentry *dentry, char *name);
int security_inode_need_killpriv(struct dentry *dentry);
@@ -2028,7 +2030,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
@@ -390,7 +390,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/security.c
+++ b/security/security.c
@@ -482,11 +482,12 @@ void security_inode_post_setxattr(struct
security_ops->inode_post_setxattr(dentry, mnt, name, value, size, flags);
}
-int security_inode_getxattr(struct dentry *dentry, char *name)
+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);
}
int security_inode_listxattr(struct dentry *dentry)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2673,7 +2673,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);
}

View File

@@ -1,134 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: 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 <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 3 ++-
include/linux/security.h | 16 +++++++++++-----
security/dummy.c | 6 ++++--
security/security.c | 8 +++++---
security/selinux/hooks.c | 9 +++++++--
5 files changed, 29 insertions(+), 13 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2360,7 +2360,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
@@ -336,8 +336,10 @@ static inline void security_free_mnt_opt
* @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.
@@ -1294,8 +1296,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);
@@ -1559,8 +1562,9 @@ int security_inode_init_security(struct
char **name, void **value, size_t *len);
int security_inode_create(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode);
-int security_inode_link(struct dentry *old_dentry, struct inode *dir,
- struct dentry *new_dentry);
+int security_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
+ struct inode *dir, struct dentry *new_dentry,
+ struct vfsmount *new_mnt);
int security_inode_unlink(struct inode *dir, struct dentry *dentry);
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, const char *old_name);
@@ -1906,8 +1910,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
@@ -292,8 +292,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/security.c
+++ b/security/security.c
@@ -360,12 +360,14 @@ int security_inode_create(struct inode *
return security_ops->inode_create(dir, dentry, mnt, mode);
}
-int security_inode_link(struct dentry *old_dentry, struct inode *dir,
- struct dentry *new_dentry)
+int security_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
+ struct inode *dir, 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);
}
int security_inode_unlink(struct inode *dir, struct dentry *dentry)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2454,11 +2454,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)
return rc;
return may_link(dir, old_dentry, MAY_LINK);

View File

@@ -1,105 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_listxattr LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/xattr.c | 2 +-
include/linux/security.h | 9 +++++----
security/dummy.c | 2 +-
security/security.c | 4 ++--
security/selinux/hooks.c | 2 +-
5 files changed, 10 insertions(+), 9 deletions(-)
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -175,7 +175,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
@@ -442,7 +442,7 @@ static inline void security_free_mnt_opt
* 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
@@ -1332,7 +1332,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);
int (*inode_need_killpriv) (struct dentry *dentry);
int (*inode_killpriv) (struct dentry *dentry);
@@ -1603,7 +1603,7 @@ void security_inode_post_setxattr(struct
int flags);
int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
char *name);
-int security_inode_listxattr(struct dentry *dentry);
+int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt);
int security_inode_removexattr(struct dentry *dentry, char *name);
int security_inode_need_killpriv(struct dentry *dentry);
int security_inode_killpriv(struct dentry *dentry);
@@ -2036,7 +2036,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
@@ -396,7 +396,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/security.c
+++ b/security/security.c
@@ -490,11 +490,11 @@ int security_inode_getxattr(struct dentr
return security_ops->inode_getxattr(dentry, mnt, name);
}
-int security_inode_listxattr(struct dentry *dentry)
+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);
}
int security_inode_removexattr(struct dentry *dentry, char *name)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2679,7 +2679,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);
}

View File

@@ -1,106 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_mkdir LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 2 +-
include/linux/security.h | 8 ++++++--
security/dummy.c | 2 +-
security/security.c | 5 +++--
security/selinux/hooks.c | 3 ++-
5 files changed, 13 insertions(+), 7 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2012,7 +2012,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
@@ -355,6 +355,7 @@ static inline void security_free_mnt_opt
* 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:
@@ -1295,7 +1296,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);
@@ -1559,7 +1561,8 @@ int security_inode_link(struct dentry *o
int security_inode_unlink(struct inode *dir, struct dentry *dentry);
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
const char *old_name);
-int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode);
+int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt, int mode);
int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
@@ -1920,6 +1923,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
@@ -310,7 +310,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/security.c
+++ b/security/security.c
@@ -383,11 +383,12 @@ int security_inode_symlink(struct inode
return security_ops->inode_symlink(dir, dentry, old_name);
}
-int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+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);
}
int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2479,7 +2479,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);
}

View File

@@ -1,124 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_mknod LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 6 +++---
include/linux/security.h | 7 +++++--
security/dummy.c | 2 +-
security/security.c | 5 +++--
security/selinux/hooks.c | 5 +++--
5 files changed, 15 insertions(+), 10 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1935,7 +1935,7 @@ int vfs_mknod(struct inode *dir, struct
if (!dir->i_op || !dir->i_op->mknod)
return -EPERM;
- error = security_inode_mknod(dir, dentry, mode, dev);
+ error = security_inode_mknod(dir, dentry, mnt, mode, dev);
if (error)
return error;
@@ -1975,11 +1975,11 @@ asmlinkage long sys_mknodat(int dfd, con
break;
case S_IFCHR: case S_IFBLK:
error = vfs_mknod(nd.path.dentry->d_inode, dentry,
- nd.path, mode, new_decode_dev(dev));
+ nd.path.mnt, mode, new_decode_dev(dev));
break;
case S_IFIFO: case S_IFSOCK:
error = vfs_mknod(nd.path.dentry->d_inode, dentry,
- nd.path, mode, 0);
+ nd.path.mnt, mode, 0);
break;
case S_IFDIR:
error = -EPERM;
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -370,6 +370,7 @@ static inline void security_free_mnt_opt
* and not this hook.
* @dir contains the inode structure of parent of the new file.
* @dentry contains the dentry structure of the new file.
+ * @mnt is the vfsmount corresponding to @dentry (may be NULL).
* @mode contains the mode of the new file.
* @dev contains the device number.
* Return 0 if permission is granted.
@@ -1300,7 +1301,7 @@ struct security_operations {
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);
+ 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);
@@ -1564,7 +1565,8 @@ int security_inode_symlink(struct inode
int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode);
int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
-int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
+int security_inode_mknod(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt, int mode, dev_t dev);
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry);
int security_inode_readlink(struct dentry *dentry);
@@ -1937,6 +1939,7 @@ static inline int security_inode_rmdir (
static inline int security_inode_mknod (struct inode *dir,
struct dentry *dentry,
+ struct vfsmount *mnt,
int mode, dev_t dev)
{
return 0;
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -321,7 +321,7 @@ static int dummy_inode_rmdir (struct ino
}
static int dummy_inode_mknod (struct inode *inode, struct dentry *dentry,
- int mode, dev_t dev)
+ struct vfsmount *mnt, int mode, dev_t dev)
{
return 0;
}
--- a/security/security.c
+++ b/security/security.c
@@ -398,11 +398,12 @@ int security_inode_rmdir(struct inode *d
return security_ops->inode_rmdir(dir, dentry);
}
-int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+int security_inode_mknod(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt, int mode, dev_t dev)
{
if (unlikely(IS_PRIVATE(dir)))
return 0;
- return security_ops->inode_mknod(dir, dentry, mode, dev);
+ return security_ops->inode_mknod(dir, dentry, mnt, mode, dev);
}
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2490,11 +2490,12 @@ static int selinux_inode_rmdir(struct in
return may_link(dir, dentry, MAY_RMDIR);
}
-static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt, int mode, dev_t dev)
{
int rc;
- rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
+ rc = secondary_ops->inode_mknod(dir, dentry, mnt, mode, dev);
if (rc)
return rc;

View File

@@ -1,104 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_readlink LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/stat.c | 2 +-
include/linux/security.h | 8 +++++---
security/dummy.c | 2 +-
security/security.c | 4 ++--
security/selinux/hooks.c | 2 +-
5 files changed, 10 insertions(+), 8 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.path.dentry);
+ error = security_inode_readlink(nd.path.dentry, nd.path.mnt);
if (!error) {
touch_atime(nd.path.mnt, nd.path.dentry);
error = inode->i_op->readlink(nd.path.dentry,
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -385,6 +385,7 @@ static inline void security_free_mnt_opt
* @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.
@@ -1305,7 +1306,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,
@@ -1570,7 +1571,7 @@ int security_inode_mknod(struct inode *d
struct vfsmount *mnt, int mode, dev_t dev);
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry);
-int security_inode_readlink(struct dentry *dentry);
+int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt);
int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
int security_inode_permission(struct inode *inode, int mask, struct nameidata *nd);
int security_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
@@ -1955,7 +1956,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
@@ -334,7 +334,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/security.c
+++ b/security/security.c
@@ -416,11 +416,11 @@ int security_inode_rename(struct inode *
new_dir, new_dentry);
}
-int security_inode_readlink(struct dentry *dentry)
+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);
}
int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2509,7 +2509,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);
}

View File

@@ -1,126 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_removexattr LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/xattr.c | 2 +-
include/linux/security.h | 13 ++++++++-----
security/commoncap.c | 3 ++-
security/dummy.c | 3 ++-
security/security.c | 5 +++--
security/selinux/hooks.c | 3 ++-
6 files changed, 18 insertions(+), 11 deletions(-)
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -203,7 +203,7 @@ vfs_removexattr(struct dentry *dentry, s
if (error)
return error;
- error = security_inode_removexattr(dentry, name);
+ error = security_inode_removexattr(dentry, mnt, name);
if (error)
return error;
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -52,7 +52,7 @@ extern int cap_bprm_set_security (struct
extern void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe);
extern int cap_bprm_secureexec(struct linux_binprm *bprm);
extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, void *value, size_t size, int flags);
-extern int cap_inode_removexattr(struct dentry *dentry, char *name);
+extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name);
extern int cap_inode_need_killpriv(struct dentry *dentry);
extern int cap_inode_killpriv(struct dentry *dentry);
extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
@@ -1333,7 +1333,8 @@ struct security_operations {
int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
char *name);
int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt);
- int (*inode_removexattr) (struct dentry *dentry, char *name);
+ int (*inode_removexattr) (struct dentry *dentry, struct vfsmount *mnt,
+ char *name);
int (*inode_need_killpriv) (struct dentry *dentry);
int (*inode_killpriv) (struct dentry *dentry);
int (*inode_getsecurity)(const struct inode *inode, const char *name, void **buffer, bool alloc);
@@ -1604,7 +1605,8 @@ void security_inode_post_setxattr(struct
int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
char *name);
int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt);
-int security_inode_removexattr(struct dentry *dentry, char *name);
+int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name);
int security_inode_need_killpriv(struct dentry *dentry);
int security_inode_killpriv(struct dentry *dentry);
int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc);
@@ -2042,9 +2044,10 @@ static inline int security_inode_listxat
return 0;
}
-static inline int security_inode_removexattr (struct dentry *dentry, char *name)
+static inline int security_inode_removexattr (struct dentry *dentry,
+ struct vfsmount *mnt, char *name)
{
- return cap_inode_removexattr(dentry, name);
+ return cap_inode_removexattr(dentry, mnt, name);
}
static inline int security_inode_need_killpriv(struct dentry *dentry)
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -400,7 +400,8 @@ int cap_inode_setxattr(struct dentry *de
return 0;
}
-int cap_inode_removexattr(struct dentry *dentry, char *name)
+int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name)
{
if (!strcmp(name, XATTR_NAME_CAPS)) {
if (!capable(CAP_SETFCAP))
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -401,7 +401,8 @@ static int dummy_inode_listxattr (struct
return 0;
}
-static int dummy_inode_removexattr (struct dentry *dentry, char *name)
+static int dummy_inode_removexattr (struct dentry *dentry, struct vfsmount *mnt,
+ char *name)
{
if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof(XATTR_SECURITY_PREFIX) - 1) &&
--- a/security/security.c
+++ b/security/security.c
@@ -497,11 +497,12 @@ int security_inode_listxattr(struct dent
return security_ops->inode_listxattr(dentry, mnt);
}
-int security_inode_removexattr(struct dentry *dentry, char *name)
+int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- return security_ops->inode_removexattr(dentry, name);
+ return security_ops->inode_removexattr(dentry, mnt, name);
}
int security_inode_need_killpriv(struct dentry *dentry)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2684,7 +2684,8 @@ static int selinux_inode_listxattr (stru
return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
}
-static int selinux_inode_removexattr (struct dentry *dentry, char *name)
+static int selinux_inode_removexattr (struct dentry *dentry,
+ struct vfsmount *mnt, char *name)
{
if (strcmp(name, XATTR_NAME_SELINUX))
return selinux_inode_setotherxattr(dentry, name);

View File

@@ -1,136 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_rename LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 6 ++++--
include/linux/security.h | 13 ++++++++++---
security/dummy.c | 4 +++-
security/security.c | 7 ++++---
security/selinux/hooks.c | 8 ++++++--
5 files changed, 27 insertions(+), 11 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2484,7 +2484,8 @@ static int vfs_rename_dir(struct inode *
return error;
}
- error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry);
+ error = security_inode_rename(old_dir, old_dentry, old_mnt,
+ new_dir, new_dentry, new_mnt);
if (error)
return error;
@@ -2518,7 +2519,8 @@ static int vfs_rename_other(struct inode
struct inode *target;
int error;
- error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry);
+ error = security_inode_rename(old_dir, old_dentry, old_mnt,
+ new_dir, new_dentry, new_mnt);
if (error)
return error;
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -383,8 +383,10 @@ static inline void security_free_mnt_opt
* Check for permission to rename a file or directory.
* @old_dir contains the inode structure for parent of the old link.
* @old_dentry contains the dentry structure of the old link.
+ * @old_mnt is the vfsmount corresponding to @old_dentry (may be NULL).
* @new_dir contains the inode structure for parent of the new link.
* @new_dentry contains the dentry structure of the new link.
+ * @new_mnt is the vfsmount corresponding to @new_dentry (may be NULL).
* Return 0 if permission is granted.
* @inode_readlink:
* Check the permission to read the symbolic link.
@@ -1312,7 +1314,9 @@ struct security_operations {
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,
- struct inode *new_dir, struct dentry *new_dentry);
+ struct vfsmount *old_mnt,
+ struct inode *new_dir, struct dentry *new_dentry,
+ struct vfsmount *new_mnt);
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);
@@ -1580,7 +1584,8 @@ int security_inode_rmdir(struct inode *d
int security_inode_mknod(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode, dev_t dev);
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry);
+ struct vfsmount *old_mnt, struct inode *new_dir,
+ struct dentry *new_dentry, struct vfsmount *new_mnt);
int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt);
int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
int security_inode_permission(struct inode *inode, int mask, struct nameidata *nd);
@@ -1964,8 +1969,10 @@ static inline int security_inode_mknod (
static inline int security_inode_rename (struct inode *old_dir,
struct dentry *old_dentry,
+ struct vfsmount *old_mnt,
struct inode *new_dir,
- struct dentry *new_dentry)
+ struct dentry *new_dentry,
+ struct vfsmount *new_mnt)
{
return 0;
}
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -332,8 +332,10 @@ static int dummy_inode_mknod (struct ino
static int dummy_inode_rename (struct inode *old_inode,
struct dentry *old_dentry,
+ struct vfsmount *old_mnt,
struct inode *new_inode,
- struct dentry *new_dentry)
+ struct dentry *new_dentry,
+ struct vfsmount *new_mnt)
{
return 0;
}
--- a/security/security.c
+++ b/security/security.c
@@ -411,13 +411,14 @@ int security_inode_mknod(struct inode *d
}
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
+ struct vfsmount *old_mnt, struct inode *new_dir,
+ struct dentry *new_dentry, struct vfsmount *new_mnt)
{
if (unlikely(IS_PRIVATE(old_dentry->d_inode) ||
(new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode))))
return 0;
- return security_ops->inode_rename(old_dir, old_dentry,
- new_dir, new_dentry);
+ return security_ops->inode_rename(old_dir, old_dentry, old_mnt,
+ new_dir, new_dentry, new_mnt);
}
int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2510,8 +2510,12 @@ static int selinux_inode_mknod(struct in
return may_create(dir, dentry, inode_mode_to_security_class(mode));
}
-static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
- struct inode *new_inode, struct dentry *new_dentry)
+static int selinux_inode_rename(struct inode *old_inode,
+ struct dentry *old_dentry,
+ struct vfsmount *old_mnt,
+ struct inode *new_inode,
+ struct dentry *new_dentry,
+ struct vfsmount *new_mnt)
{
return may_rename(old_inode, old_dentry, new_inode, new_dentry);
}

View File

@@ -1,109 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_rmdir LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 2 +-
include/linux/security.h | 10 +++++++---
security/dummy.c | 3 ++-
security/security.c | 5 +++--
security/selinux/hooks.c | 3 ++-
5 files changed, 15 insertions(+), 8 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2107,7 +2107,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
@@ -365,6 +365,7 @@ static inline void security_free_mnt_opt
* 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
@@ -1304,7 +1305,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,
@@ -1570,7 +1572,8 @@ int security_inode_symlink(struct inode
struct vfsmount *mnt, const char *old_name);
int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode);
-int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
+int security_inode_rmdir(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt);
int security_inode_mknod(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode, dev_t dev);
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
@@ -1941,7 +1944,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
@@ -317,7 +317,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/security.c
+++ b/security/security.c
@@ -393,11 +393,12 @@ int security_inode_mkdir(struct inode *d
return security_ops->inode_mkdir(dir, dentry, mnt, mode);
}
-int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
+int security_inode_rmdir(struct inode *dir, 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);
}
int security_inode_mknod(struct inode *dir, struct dentry *dentry,
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2491,7 +2491,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);
}

View File

@@ -1,119 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_setattr LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/attr.c | 4 ++--
include/linux/security.h | 8 ++++++--
security/dummy.c | 3 ++-
security/security.c | 5 +++--
security/selinux/hooks.c | 5 +++--
5 files changed, 16 insertions(+), 9 deletions(-)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -159,13 +159,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
@@ -405,6 +405,7 @@ static inline void security_free_mnt_opt
* 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:
@@ -1303,7 +1304,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,
@@ -1565,7 +1567,8 @@ int security_inode_rename(struct inode *
int security_inode_readlink(struct dentry *dentry);
int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
int security_inode_permission(struct inode *inode, int mask, struct nameidata *nd);
-int security_inode_setattr(struct dentry *dentry, struct iattr *attr);
+int security_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
+ struct iattr *attr);
int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
void security_inode_delete(struct inode *inode);
int security_inode_setxattr(struct dentry *dentry, char *name,
@@ -1961,6 +1964,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
@@ -350,7 +350,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/security.c
+++ b/security/security.c
@@ -435,11 +435,12 @@ int security_inode_permission(struct ino
return security_ops->inode_permission(inode, mask, nd);
}
-int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
+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);
}
int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2539,11 +2539,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;

View File

@@ -1,210 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_setxattr LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/xattr.c | 4 ++--
include/linux/security.h | 35 +++++++++++++++++++++--------------
security/commoncap.c | 4 ++--
security/dummy.c | 9 ++++++---
security/security.c | 14 ++++++++------
security/selinux/hooks.c | 8 ++++++--
6 files changed, 45 insertions(+), 29 deletions(-)
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -79,7 +79,7 @@ vfs_setxattr(struct dentry *dentry, stru
return error;
mutex_lock(&inode->i_mutex);
- error = security_inode_setxattr(dentry, name, value, size, flags);
+ error = security_inode_setxattr(dentry, mnt, name, value, size, flags);
if (error)
goto out;
error = -EOPNOTSUPP;
@@ -87,7 +87,7 @@ vfs_setxattr(struct dentry *dentry, stru
error = inode->i_op->setxattr(dentry, name, value, size, flags);
if (!error) {
fsnotify_xattr(dentry);
- security_inode_post_setxattr(dentry, name, value,
+ security_inode_post_setxattr(dentry, mnt, name, value,
size, flags);
}
} else if (!strncmp(name, XATTR_SECURITY_PREFIX,
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -51,7 +51,7 @@ extern void cap_capset_set (struct task_
extern int cap_bprm_set_security (struct linux_binprm *bprm);
extern void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe);
extern int cap_bprm_secureexec(struct linux_binprm *bprm);
-extern int cap_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags);
+extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, void *value, size_t size, int flags);
extern int cap_inode_removexattr(struct dentry *dentry, char *name);
extern int cap_inode_need_killpriv(struct dentry *dentry);
extern int cap_inode_killpriv(struct dentry *dentry);
@@ -431,11 +431,11 @@ static inline void security_free_mnt_opt
* inode.
* @inode_setxattr:
* Check permission before setting the extended attributes
- * @value identified by @name for @dentry.
+ * @value identified by @name for @dentry and @mnt.
* Return 0 if permission is granted.
* @inode_post_setxattr:
* Update inode security field after successful setxattr operation.
- * @value identified by @name for @dentry.
+ * @value identified by @name for @dentry and @mnt.
* @inode_getxattr:
* Check permission before obtaining the extended attributes
* identified by @name for @dentry.
@@ -1324,9 +1324,11 @@ struct security_operations {
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,
- size_t size, int flags);
- void (*inode_post_setxattr) (struct dentry *dentry, char *name, void *value,
+ int (*inode_setxattr) (struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size, int flags);
+ void (*inode_post_setxattr) (struct dentry *dentry,
+ struct vfsmount *mnt,
+ char *name, void *value,
size_t size, int flags);
int (*inode_getxattr) (struct dentry *dentry, char *name);
int (*inode_listxattr) (struct dentry *dentry);
@@ -1593,10 +1595,11 @@ int security_inode_setattr(struct dentry
struct iattr *attr);
int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
void security_inode_delete(struct inode *inode);
-int security_inode_setxattr(struct dentry *dentry, char *name,
- void *value, size_t size, int flags);
-void security_inode_post_setxattr(struct dentry *dentry, char *name,
- void *value, size_t size, int flags);
+int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size, int flags);
+void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size,
+ int flags);
int security_inode_getxattr(struct dentry *dentry, char *name);
int security_inode_listxattr(struct dentry *dentry);
int security_inode_removexattr(struct dentry *dentry, char *name);
@@ -2011,14 +2014,18 @@ static inline int security_inode_getattr
static inline void security_inode_delete (struct inode *inode)
{ }
-static inline int security_inode_setxattr (struct dentry *dentry, char *name,
+static inline int security_inode_setxattr (struct dentry *dentry,
+ struct vfsmount *mnt, char *name,
void *value, size_t size, int flags)
{
- return cap_inode_setxattr(dentry, name, value, size, flags);
+ return cap_inode_setxattr(dentry, mnt, name, value, size, flags);
}
-static inline void security_inode_post_setxattr (struct dentry *dentry, char *name,
- void *value, size_t size, int flags)
+static inline void security_inode_post_setxattr (struct dentry *dentry,
+ struct vfsmount *mnt,
+ char *name,
+ void *value, size_t size,
+ int flags)
{ }
static inline int security_inode_getxattr (struct dentry *dentry, char *name)
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -386,8 +386,8 @@ int cap_bprm_secureexec (struct linux_bi
current->egid != current->gid);
}
-int cap_inode_setxattr(struct dentry *dentry, char *name, void *value,
- size_t size, int flags)
+int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
+ void *value, size_t size, int flags)
{
if (!strcmp(name, XATTR_NAME_CAPS)) {
if (!capable(CAP_SETFCAP))
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -372,8 +372,9 @@ static void dummy_inode_delete (struct i
return;
}
-static int dummy_inode_setxattr (struct dentry *dentry, char *name, void *value,
- size_t size, int flags)
+static int dummy_inode_setxattr (struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size,
+ int flags)
{
if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof(XATTR_SECURITY_PREFIX) - 1) &&
@@ -382,7 +383,9 @@ static int dummy_inode_setxattr (struct
return 0;
}
-static void dummy_inode_post_setxattr (struct dentry *dentry, char *name, void *value,
+static void dummy_inode_post_setxattr (struct dentry *dentry,
+ struct vfsmount *mnt,
+ char *name, void *value,
size_t size, int flags)
{
}
--- a/security/security.c
+++ b/security/security.c
@@ -464,20 +464,22 @@ void security_inode_delete(struct inode
security_ops->inode_delete(inode);
}
-int security_inode_setxattr(struct dentry *dentry, char *name,
- void *value, size_t size, int flags)
+int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size, int flags)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- return security_ops->inode_setxattr(dentry, name, value, size, flags);
+ return security_ops->inode_setxattr(dentry, mnt, name, value, size,
+ flags);
}
-void security_inode_post_setxattr(struct dentry *dentry, char *name,
- void *value, size_t size, int flags)
+void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size,
+ int flags)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return;
- security_ops->inode_post_setxattr(dentry, name, value, size, flags);
+ security_ops->inode_post_setxattr(dentry, mnt, name, value, size, flags);
}
int security_inode_getxattr(struct dentry *dentry, char *name)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2596,7 +2596,9 @@ static int selinux_inode_setotherxattr(s
return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
}
-static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
+static int selinux_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+ char *name, void *value, size_t size,
+ int flags)
{
struct task_security_struct *tsec = current->security;
struct inode *inode = dentry->d_inode;
@@ -2645,7 +2647,9 @@ static int selinux_inode_setxattr(struct
&ad);
}
-static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
+static void selinux_inode_post_setxattr(struct dentry *dentry,
+ struct vfsmount *mnt,
+ char *name,
void *value, size_t size, int flags)
{
struct inode *inode = dentry->d_inode;

View File

@@ -1,105 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_symlink LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 2 +-
include/linux/security.h | 8 +++++---
security/dummy.c | 2 +-
security/security.c | 4 ++--
security/selinux/hooks.c | 3 ++-
5 files changed, 11 insertions(+), 8 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2281,7 +2281,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
@@ -348,6 +348,7 @@ static inline void security_free_mnt_opt
* 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:
@@ -1295,8 +1296,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);
@@ -1561,7 +1562,7 @@ int security_inode_link(struct dentry *o
struct dentry *new_dentry);
int security_inode_unlink(struct inode *dir, struct dentry *dentry);
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
- const char *old_name);
+ struct vfsmount *mnt, const char *old_name);
int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, int mode);
int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
@@ -1918,6 +1919,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
@@ -304,7 +304,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/security.c
+++ b/security/security.c
@@ -376,11 +376,11 @@ int security_inode_unlink(struct inode *
}
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
- const char *old_name)
+ 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);
}
int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2474,7 +2474,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);
}

View File

@@ -1,114 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Pass struct vfsmount to the inode_unlink LSM hook
This is needed for computing pathnames in the AppArmor LSM.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/namei.c | 2 +-
include/linux/security.h | 10 +++++++---
security/dummy.c | 3 ++-
security/security.c | 5 +++--
security/selinux/hooks.c | 5 +++--
5 files changed, 16 insertions(+), 9 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2187,7 +2187,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
@@ -345,6 +345,7 @@ static inline void security_free_mnt_opt
* 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.
@@ -1300,7 +1301,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,
@@ -1567,7 +1569,8 @@ int security_inode_create(struct inode *
int security_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
struct inode *dir, struct dentry *new_dentry,
struct vfsmount *new_mnt);
-int security_inode_unlink(struct inode *dir, struct dentry *dentry);
+int security_inode_unlink(struct inode *dir, struct dentry *dentry,
+ struct vfsmount *mnt);
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
struct vfsmount *mnt, const char *old_name);
int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
@@ -1922,7 +1925,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
@@ -300,7 +300,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/security.c
+++ b/security/security.c
@@ -370,11 +370,12 @@ int security_inode_link(struct dentry *o
new_dentry, new_mnt);
}
-int security_inode_unlink(struct inode *dir, struct dentry *dentry)
+int security_inode_unlink(struct inode *dir, 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);
}
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2469,11 +2469,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);

View File

@@ -1,541 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: 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 <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/xattr.c | 58 ++++++++++++++++++++++++-----------------------
include/linux/security.h | 40 +++++++++++++++++++-------------
include/linux/xattr.h | 10 ++++----
security/commoncap.c | 4 +--
security/dummy.c | 10 ++++----
security/security.c | 21 +++++++++--------
security/selinux/hooks.c | 10 ++++----
7 files changed, 86 insertions(+), 67 deletions(-)
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -69,7 +69,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;
@@ -79,7 +79,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;
@@ -133,7 +133,7 @@ EXPORT_SYMBOL_GPL(xattr_getsecurity);
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;
@@ -142,7 +142,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;
@@ -170,12 +170,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;
@@ -191,7 +191,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;
@@ -203,7 +204,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;
@@ -223,7 +224,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;
@@ -250,7 +251,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;
}
@@ -265,7 +266,7 @@ sys_setxattr(char __user *path, char __u
error = user_path_walk(path, &nd);
if (error)
return error;
- error = setxattr(nd.path.dentry, nd.path.mnt, name, value, size, flags);
+ error = setxattr(nd.path.dentry, nd.path.mnt, name, value, size, flags, NULL);
path_put(&nd.path);
return error;
}
@@ -280,7 +281,7 @@ sys_lsetxattr(char __user *path, char __
error = user_path_walk_link(path, &nd);
if (error)
return error;
- error = setxattr(nd.path.dentry, nd.path.mnt, name, value, size, flags);
+ error = setxattr(nd.path.dentry, nd.path.mnt, name, value, size, flags, NULL);
path_put(&nd.path);
return error;
}
@@ -298,7 +299,7 @@ sys_fsetxattr(int fd, char __user *name,
return error;
dentry = f->f_path.dentry;
audit_inode(NULL, dentry);
- 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;
}
@@ -308,7 +309,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 size)
+ void __user *value, size_t size, struct file *file)
{
ssize_t error;
void *kvalue = NULL;
@@ -328,7 +329,7 @@ getxattr(struct dentry *dentry, struct v
return -ENOMEM;
}
- error = vfs_getxattr(dentry, mnt, kname, kvalue, size);
+ error = vfs_getxattr(dentry, mnt, kname, kvalue, size, file);
if (error > 0) {
if (size && copy_to_user(value, kvalue, error))
error = -EFAULT;
@@ -351,7 +352,7 @@ sys_getxattr(char __user *path, char __u
error = user_path_walk(path, &nd);
if (error)
return error;
- error = getxattr(nd.path.dentry, nd.path.mnt, name, value, size);
+ error = getxattr(nd.path.dentry, nd.path.mnt, name, value, size, NULL);
path_put(&nd.path);
return error;
}
@@ -366,7 +367,7 @@ sys_lgetxattr(char __user *path, char __
error = user_path_walk_link(path, &nd);
if (error)
return error;
- error = getxattr(nd.path.dentry, nd.path.mnt, name, value, size);
+ error = getxattr(nd.path.dentry, nd.path.mnt, name, value, size, NULL);
path_put(&nd.path);
return error;
}
@@ -381,7 +382,7 @@ sys_fgetxattr(int fd, char __user *name,
if (!f)
return error;
audit_inode(NULL, f->f_path.dentry);
- error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size);
+ error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size, f);
fput(f);
return error;
}
@@ -391,7 +392,7 @@ sys_fgetxattr(int fd, char __user *name,
*/
static ssize_t
listxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *list,
- size_t size)
+ size_t size, struct file *file)
{
ssize_t error;
char *klist = NULL;
@@ -404,7 +405,7 @@ listxattr(struct dentry *dentry, struct
return -ENOMEM;
}
- error = vfs_listxattr(dentry, mnt, klist, size);
+ error = vfs_listxattr(dentry, mnt, klist, size, file);
if (error > 0) {
if (size && copy_to_user(list, klist, error))
error = -EFAULT;
@@ -426,7 +427,7 @@ sys_listxattr(char __user *path, char __
error = user_path_walk(path, &nd);
if (error)
return error;
- error = listxattr(nd.path.dentry, nd.path.mnt, list, size);
+ error = listxattr(nd.path.dentry, nd.path.mnt, list, size, NULL);
path_put(&nd.path);
return error;
}
@@ -440,7 +441,7 @@ sys_llistxattr(char __user *path, char _
error = user_path_walk_link(path, &nd);
if (error)
return error;
- error = listxattr(nd.path.dentry, nd.path.mnt, list, size);
+ error = listxattr(nd.path.dentry, nd.path.mnt, list, size, NULL);
path_put(&nd.path);
return error;
}
@@ -455,7 +456,7 @@ sys_flistxattr(int fd, char __user *list
if (!f)
return error;
audit_inode(NULL, f->f_path.dentry);
- error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size);
+ error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size, f);
fput(f);
return error;
}
@@ -464,7 +465,8 @@ sys_flistxattr(int fd, char __user *list
* Extended attribute REMOVE operations
*/
static long
-removexattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name)
+removexattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name,
+ struct file *file)
{
int error;
char kname[XATTR_NAME_MAX + 1];
@@ -475,7 +477,7 @@ removexattr(struct dentry *dentry, struc
if (error < 0)
return error;
- return vfs_removexattr(dentry, mnt, kname);
+ return vfs_removexattr(dentry, mnt, kname, file);
}
asmlinkage long
@@ -487,7 +489,7 @@ sys_removexattr(char __user *path, char
error = user_path_walk(path, &nd);
if (error)
return error;
- error = removexattr(nd.path.dentry, nd.path.mnt, name);
+ error = removexattr(nd.path.dentry, nd.path.mnt, name, NULL);
path_put(&nd.path);
return error;
}
@@ -501,7 +503,7 @@ sys_lremovexattr(char __user *path, char
error = user_path_walk_link(path, &nd);
if (error)
return error;
- error = removexattr(nd.path.dentry, nd.path.mnt, name);
+ error = removexattr(nd.path.dentry, nd.path.mnt, name, NULL);
path_put(&nd.path);
return error;
}
@@ -518,7 +520,7 @@ sys_fremovexattr(int fd, char __user *na
return error;
dentry = f->f_path.dentry;
audit_inode(NULL, dentry);
- error = removexattr(dentry, f->f_path.mnt, name);
+ error = removexattr(dentry, f->f_path.mnt, name, f);
fput(f);
return error;
}
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -51,8 +51,8 @@ extern void cap_capset_set (struct task_
extern int cap_bprm_set_security (struct linux_binprm *bprm);
extern void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe);
extern int cap_bprm_secureexec(struct linux_binprm *bprm);
-extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, void *value, size_t size, int flags);
-extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name);
+extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, void *value, size_t size, int flags, struct file *file);
+extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name, struct file *file);
extern int cap_inode_need_killpriv(struct dentry *dentry);
extern int cap_inode_killpriv(struct dentry *dentry);
extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
@@ -1325,16 +1325,18 @@ struct security_operations {
int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
void (*inode_delete) (struct inode *inode);
int (*inode_setxattr) (struct dentry *dentry, struct vfsmount *mnt,
- char *name, void *value, size_t size, int flags);
+ char *name, void *value, size_t size, int flags,
+ struct file *file);
void (*inode_post_setxattr) (struct dentry *dentry,
struct vfsmount *mnt,
char *name, void *value,
size_t size, int flags);
int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
- char *name);
- int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt);
+ char *name, struct file *file);
+ int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt,
+ struct file *file);
int (*inode_removexattr) (struct dentry *dentry, struct vfsmount *mnt,
- char *name);
+ char *name, struct file *file);
int (*inode_need_killpriv) (struct dentry *dentry);
int (*inode_killpriv) (struct dentry *dentry);
int (*inode_getsecurity)(const struct inode *inode, const char *name, void **buffer, bool alloc);
@@ -1598,15 +1600,17 @@ int security_inode_setattr(struct dentry
int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
void security_inode_delete(struct inode *inode);
int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name, void *value, size_t size, int flags);
+ char *name, void *value, size_t size, int flags,
+ struct file *file);
void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
char *name, void *value, size_t size,
int flags);
int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name);
-int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt);
+ char *name, struct file *file);
+int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
+ struct file *file);
int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name);
+ char *name, struct file *file);
int security_inode_need_killpriv(struct dentry *dentry);
int security_inode_killpriv(struct dentry *dentry);
int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc);
@@ -2020,9 +2024,10 @@ static inline void security_inode_delete
static inline int security_inode_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)
{
- return cap_inode_setxattr(dentry, mnt, name, value, size, flags);
+ return cap_inode_setxattr(dentry, mnt, name, value, size, flags, file);
}
static inline void security_inode_post_setxattr (struct dentry *dentry,
@@ -2033,21 +2038,24 @@ static inline void security_inode_post_s
{ }
static inline int security_inode_getxattr (struct dentry *dentry,
- struct vfsmount *mnt, char *name)
+ struct vfsmount *mnt, char *name,
+ struct file *file)
{
return 0;
}
static inline int security_inode_listxattr (struct dentry *dentry,
- struct vfsmount *mnt)
+ struct vfsmount *mnt,
+ struct file *file)
{
return 0;
}
static inline int security_inode_removexattr (struct dentry *dentry,
- struct vfsmount *mnt, char *name)
+ struct vfsmount *mnt, char *name,
+ struct file *file)
{
- return cap_inode_removexattr(dentry, mnt, name);
+ return cap_inode_removexattr(dentry, mnt, name, file);
}
static inline int security_inode_need_killpriv(struct dentry *dentry)
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -47,11 +47,13 @@ struct xattr_handler {
};
ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
-ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, char *, void *, size_t);
-ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list, size_t size);
+ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, char *, void *,
+ size_t, struct file *);
+ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list,
+ size_t size, struct file *);
int vfs_setxattr(struct dentry *, struct vfsmount *, char *, void *, size_t,
- int);
-int vfs_removexattr(struct dentry *, struct vfsmount *, char *);
+ int, struct file *);
+int vfs_removexattr(struct dentry *, struct vfsmount *, char *, struct file *);
ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -387,7 +387,7 @@ int cap_bprm_secureexec (struct linux_bi
}
int cap_inode_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)
{
if (!strcmp(name, XATTR_NAME_CAPS)) {
if (!capable(CAP_SETFCAP))
@@ -401,7 +401,7 @@ int cap_inode_setxattr(struct dentry *de
}
int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name)
+ char *name, struct file *file)
{
if (!strcmp(name, XATTR_NAME_CAPS)) {
if (!capable(CAP_SETFCAP))
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -374,7 +374,7 @@ static void dummy_inode_delete (struct i
static int dummy_inode_setxattr (struct dentry *dentry, struct vfsmount *mnt,
char *name, void *value, size_t size,
- int flags)
+ int flags, struct file *file)
{
if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof(XATTR_SECURITY_PREFIX) - 1) &&
@@ -391,18 +391,20 @@ static void dummy_inode_post_setxattr (s
}
static int dummy_inode_getxattr (struct dentry *dentry,
- struct vfsmount *mnt, char *name)
+ struct vfsmount *mnt, char *name,
+ struct file *file)
{
return 0;
}
-static int dummy_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt)
+static int dummy_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt,
+ struct file *file)
{
return 0;
}
static int dummy_inode_removexattr (struct dentry *dentry, struct vfsmount *mnt,
- char *name)
+ char *name, struct file *file)
{
if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof(XATTR_SECURITY_PREFIX) - 1) &&
--- a/security/security.c
+++ b/security/security.c
@@ -465,12 +465,13 @@ void security_inode_delete(struct inode
}
int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name, void *value, size_t size, int flags)
+ char *name, void *value, size_t size, int flags,
+ struct file *file)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
return security_ops->inode_setxattr(dentry, mnt, name, value, size,
- flags);
+ flags, file);
}
void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
@@ -479,30 +480,32 @@ void security_inode_post_setxattr(struct
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return;
- security_ops->inode_post_setxattr(dentry, mnt, name, value, size, flags);
+ security_ops->inode_post_setxattr(dentry, mnt, name, value, size,
+ flags);
}
int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name)
+ char *name, struct file *file)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- return security_ops->inode_getxattr(dentry, mnt, name);
+ return security_ops->inode_getxattr(dentry, mnt, name, file);
}
-int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt)
+int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
+ struct file *file)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- return security_ops->inode_listxattr(dentry, mnt);
+ return security_ops->inode_listxattr(dentry, mnt, file);
}
int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
- char *name)
+ char *name, struct file *file)
{
if (unlikely(IS_PRIVATE(dentry->d_inode)))
return 0;
- return security_ops->inode_removexattr(dentry, mnt, name);
+ return security_ops->inode_removexattr(dentry, mnt, name, file);
}
int security_inode_need_killpriv(struct dentry *dentry)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2598,7 +2598,7 @@ static int selinux_inode_setotherxattr(s
static int selinux_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
char *name, void *value, size_t size,
- int flags)
+ int flags, struct file *file)
{
struct task_security_struct *tsec = current->security;
struct inode *inode = dentry->d_inode;
@@ -2674,18 +2674,20 @@ static void selinux_inode_post_setxattr(
}
static int selinux_inode_getxattr (struct dentry *dentry, struct vfsmount *mnt,
- char *name)
+ char *name, struct file *file)
{
return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
}
-static int selinux_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt)
+static int selinux_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt,
+ struct file *file)
{
return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
}
static int selinux_inode_removexattr (struct dentry *dentry,
- struct vfsmount *mnt, char *name)
+ struct vfsmount *mnt, char *name,
+ struct file *file)
{
if (strcmp(name, XATTR_NAME_SELINUX))
return selinux_inode_setotherxattr(dentry, name);

View File

@@ -1,59 +0,0 @@
#unionfs-2.2.2_for_2.6.24-rc7.diff
#unionfs-2.1.11_for_2.6.24-rc4.diff
security-create.diff
remove_suid.diff
vfs-notify_change.diff
#should_remove_suid.diff
security-setattr.diff
vfs-mkdir.diff
security-mkdir.diff
vfs-mknod.diff
security-mknod.diff
vfs-symlink.diff
security-symlink.diff
security-readlink.diff
vfs-link.diff
security-link.diff
vfs-rmdir.diff
security-rmdir.diff
fix-vfs_rmdir.diff
vfs-unlink.diff
security-unlink.diff
vfs-rename.diff
security-rename.diff
vfs-setxattr.diff
security-setxattr.diff
vfs-getxattr.diff
security-getxattr.diff
vfs-listxattr.diff
security-listxattr.diff
vfs-removexattr.diff
security-removexattr.diff
unambiguous-__d_path.diff
mount-consistent-__d_path.diff
d_namespace_path.diff
__d_path-keep-connected.diff
#fgetattr.diff
fsetattr.diff
#fix-fuse.diff
fsetattr-reintro-ATTR_FILE.diff
file-handle-ops.diff
security-xattr-file.diff
sysctl-pathname.diff
parent-permission.diff
do_path_lookup-nameidata.diff
sys_fchdir-nameidata.diff
file_permission-nameidata.diff
apparmor-audit.diff
apparmor-main.diff
apparmor-lsm.diff
apparmor-module_interface.diff
apparmor-misc.diff
apparmor-intree.diff
#ptrace-bits.diff
#apparmor-ptrace.diff
#apparmor-named-transitions.diff
apparmor-network.diff
apparmor-rlimits.diff
apparmor-2.6.25.diff
apparmor-stack_secondary.diff

View File

@@ -1,40 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Switch to vfs_permission() in sys_fchdir()
Switch from file_permission() to vfs_permission() in sys_fchdir(): this
avoids calling permission() with a NULL nameidata here.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/open.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
--- a/fs/open.c
+++ b/fs/open.c
@@ -500,8 +500,8 @@ out:
asmlinkage long sys_fchdir(unsigned int fd)
{
+ struct nameidata nd = { .flags = 0 };
struct file *file;
- struct inode *inode;
int error;
error = -EBADF;
@@ -509,12 +509,11 @@ asmlinkage long sys_fchdir(unsigned int
if (!file)
goto out;
- inode = file->f_path.dentry->d_inode;
-
error = -ENOTDIR;
- if (!S_ISDIR(inode->i_mode))
+ if (!S_ISDIR(file->f_path.dentry->d_inode->i_mode))
goto out_putf;
+ nd.path = file->f_path;
error = file_permission(file, MAY_EXEC);
if (!error)
set_fs_pwd(current->fs, &file->f_path);

View File

@@ -1,111 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Factor out sysctl pathname code
Convert the selinux sysctl pathname computation code into a standalone
function.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
Reviewed-by: James Morris <jmorris@namei.org>
---
include/linux/sysctl.h | 2 ++
kernel/sysctl.c | 27 +++++++++++++++++++++++++++
security/selinux/hooks.c | 35 +++++------------------------------
3 files changed, 34 insertions(+), 30 deletions(-)
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -977,6 +977,8 @@ extern int proc_doulongvec_minmax(struct
extern int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int,
struct file *, void __user *, size_t *, loff_t *);
+extern char *sysctl_pathname(ctl_table *, char *, int);
+
extern int do_sysctl (int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen);
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1440,6 +1440,33 @@ void register_sysctl_root(struct ctl_tab
spin_unlock(&sysctl_lock);
}
+char *sysctl_pathname(struct ctl_table *table, char *buffer, int buflen)
+{
+ if (buflen < 1)
+ return NULL;
+ buffer += --buflen;
+ *buffer = '\0';
+
+ while (table) {
+ int namelen = strlen(table->procname);
+
+ if (buflen < namelen + 1)
+ return NULL;
+ buflen -= namelen + 1;
+ buffer -= namelen;
+ memcpy(buffer, table->procname, namelen);
+ *--buffer = '/';
+ table = table->parent;
+ }
+ if (buflen < 4)
+ return NULL;
+ buffer -= 4;
+ memcpy(buffer, "/sys", 4);
+
+ return buffer;
+}
+EXPORT_SYMBOL_GPL(sysctl_pathname);
+
#ifdef CONFIG_SYSCTL_SYSCALL
int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1702,40 +1702,15 @@ static int selinux_capable(struct task_s
static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
{
- int buflen, rc;
- char *buffer, *path, *end;
+ char *buffer, *path;
+ int rc = -ENOMEM;
- rc = -ENOMEM;
buffer = (char*)__get_free_page(GFP_KERNEL);
if (!buffer)
goto out;
-
- buflen = PAGE_SIZE;
- end = buffer+buflen;
- *--end = '\0';
- buflen--;
- path = end-1;
- *path = '/';
- while (table) {
- const char *name = table->procname;
- size_t namelen = strlen(name);
- buflen -= namelen + 1;
- if (buflen < 0)
- goto out_free;
- end -= namelen;
- memcpy(end, name, namelen);
- *--end = '/';
- path = end;
- table = table->parent;
- }
- buflen -= 4;
- if (buflen < 0)
- goto out_free;
- end -= 4;
- memcpy(end, "/sys", 4);
- path = end;
- rc = security_genfs_sid("proc", path, tclass, sid);
-out_free:
+ path = sysctl_pathname(table, buffer, PAGE_SIZE);
+ if (path)
+ rc = security_genfs_sid("proc", path, tclass, sid);
free_page((unsigned long)buffer);
out:
return rc;

View File

@@ -1,258 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: 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 <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
---
fs/dcache.c | 159 +++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 95 insertions(+), 64 deletions(-)
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1747,51 +1747,53 @@ 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 path *root, char *buffer, int buflen)
+ struct path *root, char *buffer, int buflen,
+ int fail_deleted)
{
- char * end = buffer+buflen;
- char * retval;
- int namelen;
+ 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->dentry || vfsmnt != root->mnt) {
struct dentry * parent;
- if (dentry == root->dentry && vfsmnt == root->mnt)
- break;
if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
- /* Global root? */
spin_lock(&vfsmount_lock);
if (vfsmnt->mnt_parent == vfsmnt) {
spin_unlock(&vfsmount_lock);
@@ -1805,28 +1807,68 @@ static char *__d_path(struct dentry *den
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 = '/';
- return retval;
+out:
+ spin_unlock(&dcache_lock);
+ return buffer;
global_root:
+ /*
+ * We went past the (vfsmount, dentry) we were looking for and have
+ * either hit a root dentry, a lazily unmounted dentry, an
+ * unconnected dentry, or the file is on a pseudo filesystem.
+ */
namelen = dentry->d_name.len;
- buflen -= namelen;
- if (buflen < 0)
+ is_slash = (namelen == 1 && *dentry->d_name.name == '/');
+ if (is_slash || (dentry->d_sb->s_flags & MS_NOUSER)) {
+ /*
+ * Make sure we won't return a pathname starting with '/'.
+ *
+ * Historically, we also glue together the root dentry and
+ * remaining name for pseudo filesystems like pipefs, which
+ * have the MS_NOUSER flag set. This results in pathnames
+ * like "pipe:[439336]".
+ */
+ if (*buffer == '/') {
+ buffer++;
+ buflen++;
+ }
+ if (is_slash)
+ goto out;
+ }
+ if (buflen < namelen)
goto Elong;
- retval -= namelen-1; /* hit the slash */
- memcpy(retval, dentry->d_name.name, namelen);
- return retval;
+ buffer -= namelen;
+ memcpy(buffer, dentry->d_name.name, namelen);
+ goto out;
+
Elong:
- return ERR_PTR(-ENAMETOOLONG);
+ buffer = ERR_PTR(-ENAMETOOLONG);
+ goto out;
+}
+
+static char *__connect_d_path(char *path, char *buffer, struct dentry *dentry)
+{
+ if (!IS_ERR(path) && *path != '/' &&
+ !(dentry->d_sb->s_flags & MS_NOUSER)) {
+ /* Pretend that disconnected paths are hanging off the root. */
+ if (path == buffer)
+ path = ERR_PTR(-ENAMETOOLONG);
+ else
+ *--path = '/';
+ }
+ return path;
}
/**
@@ -1861,9 +1903,8 @@ char *d_path(struct path *path, char *bu
root = current->fs->root;
path_get(&current->fs->root);
read_unlock(&current->fs->lock);
- spin_lock(&dcache_lock);
- res = __d_path(path->dentry, path->mnt, &root, buf, buflen);
- spin_unlock(&dcache_lock);
+ res = __d_path(path->dentry, path->mnt, &root, buf, buflen, 0);
+ res = __connect_d_path(res, buf, path->dentry);
path_put(&root);
return res;
}
@@ -1909,9 +1950,9 @@ char *dynamic_dname(struct dentry *dentr
*/
asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
{
- int error;
+ int error, len;
struct path pwd, root;
- char *page = (char *) __get_free_page(GFP_USER);
+ char *page = (char *) __get_free_page(GFP_USER), *cwd;
if (!page)
return -ENOMEM;
@@ -1923,29 +1964,19 @@ asmlinkage long sys_getcwd(char __user *
path_get(&current->fs->root);
read_unlock(&current->fs->lock);
- error = -ENOENT;
- /* Has the current directory has been unlinked? */
- spin_lock(&dcache_lock);
- if (pwd.dentry->d_parent == pwd.dentry || !d_unhashed(pwd.dentry)) {
- unsigned long len;
- char * cwd;
-
- cwd = __d_path(pwd.dentry, pwd.mnt, &root, page, PAGE_SIZE);
- spin_unlock(&dcache_lock);
-
- error = PTR_ERR(cwd);
- if (IS_ERR(cwd))
- goto out;
-
- error = -ERANGE;
- len = PAGE_SIZE + page - cwd;
- if (len <= size) {
- error = len;
- if (copy_to_user(buf, cwd, len))
- error = -EFAULT;
- }
- } else
- spin_unlock(&dcache_lock);
+ cwd = __d_path(pwd.dentry, pwd.mnt, &root, page, PAGE_SIZE, 1);
+ cwd = __connect_d_path(cwd, page, pwd.dentry);
+ error = PTR_ERR(cwd);
+ if (IS_ERR(cwd))
+ goto out;
+
+ error = -ERANGE;
+ len = PAGE_SIZE + page - cwd;
+ if (len <= size) {
+ error = len;
+ if (copy_to_user(buf, cwd, len))
+ error = -EFAULT;
+ }
out:
path_put(&pwd);

View File

@@ -1,189 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: 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 <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/nfsd/nfs4xdr.c | 2 +-
fs/nfsd/vfs.c | 21 ++++++++++++---------
fs/xattr.c | 14 ++++++++------
include/linux/nfsd/nfsd.h | 3 ++-
include/linux/xattr.h | 2 +-
5 files changed, 24 insertions(+), 18 deletions(-)
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1501,7 +1501,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_path.mnt, &acl);
aclsupport = (err == 0);
if (bmval0 & FATTR4_WORD0_ACL) {
if (err == -EOPNOTSUPP)
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -408,11 +408,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;
@@ -420,7 +421,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
@@ -501,13 +502,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)
@@ -519,14 +520,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)) {
@@ -536,7 +538,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)) {
@@ -2011,7 +2013,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_path.mnt, name,
+ &value);
if (size < 0)
return ERR_PTR(size);
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -132,7 +132,8 @@ out_noalloc:
EXPORT_SYMBOL_GPL(xattr_getsecurity);
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;
@@ -304,7 +305,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;
@@ -324,7 +326,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;
@@ -347,7 +349,7 @@ sys_getxattr(char __user *path, char __u
error = user_path_walk(path, &nd);
if (error)
return error;
- error = getxattr(nd.path.dentry, name, value, size);
+ error = getxattr(nd.path.dentry, nd.path.mnt, name, value, size);
path_put(&nd.path);
return error;
}
@@ -362,7 +364,7 @@ sys_lgetxattr(char __user *path, char __
error = user_path_walk_link(path, &nd);
if (error)
return error;
- error = getxattr(nd.path.dentry, name, value, size);
+ error = getxattr(nd.path.dentry, nd.path.mnt, name, value, size);
path_put(&nd.path);
return error;
}
@@ -377,7 +379,7 @@ sys_fgetxattr(int fd, char __user *name,
if (!f)
return error;
audit_inode(NULL, f->f_path.dentry);
- error = getxattr(f->f_path.dentry, name, value, size);
+ error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size);
fput(f);
return error;
}
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -78,7 +78,8 @@ __be32 nfsd_setattr(struct svc_rqst *,
#ifdef CONFIG_NFSD_V4
__be32 nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
struct nfs4_acl *);
-int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
+int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *,
+ struct vfsmount *mnt, struct nfs4_acl **);
#endif /* CONFIG_NFSD_V4 */
__be32 nfsd_create(struct svc_rqst *, struct svc_fh *,
char *name, int len, struct iattr *attrs,
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -47,7 +47,7 @@ struct xattr_handler {
};
ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
-ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t);
+ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, char *, void *, size_t);
ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
int vfs_setxattr(struct dentry *, struct vfsmount *, char *, void *, size_t,
int);

View File

@@ -1,90 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: 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 <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
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
@@ -388,19 +388,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
@@ -2335,7 +2335,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;
@@ -2413,7 +2413,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.path.dentry, nd.path.dentry->d_inode, new_dentry);
+ error = vfs_link(old_nd.path.dentry, old_nd.path.mnt, nd.path.dentry->d_inode,
+ new_dentry, nd.path.mnt);
dput(new_dentry);
out_unlock:
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1599,7 +1599,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_path.mnt, dirp,
+ dnew, ffhp->fh_export->ex_path.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
@@ -1079,7 +1079,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 *);

View File

@@ -1,101 +0,0 @@
From: Tony Jones <tonyj@suse.de>
Subject: Add a struct vfsmount parameter to vfs_listxattr()
The vfsmount will be passed down to the LSM hook so that LSMs can compute
pathnames.
Signed-off-by: Tony Jones <tonyj@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
fs/xattr.c | 25 ++++++++++++++-----------
include/linux/xattr.h | 2 +-
2 files changed, 15 insertions(+), 12 deletions(-)
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -169,18 +169,20 @@ nolsm:
EXPORT_SYMBOL_GPL(vfs_getxattr);
ssize_t
-vfs_listxattr(struct dentry *d, char *list, size_t size)
+vfs_listxattr(struct dentry *dentry, struct vfsmount *mnt, char *list,
+ size_t size)
{
+ struct inode *inode = dentry->d_inode;
ssize_t error;
- error = security_inode_listxattr(d);
+ error = security_inode_listxattr(dentry);
if (error)
return error;
error = -EOPNOTSUPP;
- if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
- error = d->d_inode->i_op->listxattr(d, list, size);
- } else {
- error = security_inode_listsecurity(d->d_inode, list, size);
+ if (inode->i_op && inode->i_op->listxattr)
+ error = inode->i_op->listxattr(dentry, list, size);
+ else {
+ error = security_inode_listsecurity(inode, list, size);
if (size && error > size)
error = -ERANGE;
}
@@ -388,7 +390,8 @@ sys_fgetxattr(int fd, char __user *name,
* Extended attribute LIST operations
*/
static ssize_t
-listxattr(struct dentry *d, char __user *list, size_t size)
+listxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *list,
+ size_t size)
{
ssize_t error;
char *klist = NULL;
@@ -401,7 +404,7 @@ listxattr(struct dentry *d, char __user
return -ENOMEM;
}
- error = vfs_listxattr(d, klist, size);
+ error = vfs_listxattr(dentry, mnt, klist, size);
if (error > 0) {
if (size && copy_to_user(list, klist, error))
error = -EFAULT;
@@ -423,7 +426,7 @@ sys_listxattr(char __user *path, char __
error = user_path_walk(path, &nd);
if (error)
return error;
- error = listxattr(nd.path.dentry, list, size);
+ error = listxattr(nd.path.dentry, nd.path.mnt, list, size);
path_put(&nd.path);
return error;
}
@@ -437,7 +440,7 @@ sys_llistxattr(char __user *path, char _
error = user_path_walk_link(path, &nd);
if (error)
return error;
- error = listxattr(nd.path.dentry, list, size);
+ error = listxattr(nd.path.dentry, nd.path.mnt, list, size);
path_put(&nd.path);
return error;
}
@@ -452,7 +455,7 @@ sys_flistxattr(int fd, char __user *list
if (!f)
return error;
audit_inode(NULL, f->f_path.dentry);
- error = listxattr(f->f_path.dentry, list, size);
+ error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size);
fput(f);
return error;
}
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -48,7 +48,7 @@ struct xattr_handler {
ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, char *, void *, size_t);
-ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
+ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list, size_t size);
int vfs_setxattr(struct dentry *, struct vfsmount *, char *, void *, size_t,
int);
int vfs_removexattr(struct dentry *, char *);

Some files were not shown because too many files have changed in this diff Show More