All of lore.kernel.org
 help / color / mirror / Atom feed
* kernel crash in mknod
@ 2024-03-24  5:00 Steve French
  2024-03-24  5:46 ` Al Viro
  0 siblings, 1 reply; 22+ messages in thread
From: Steve French @ 2024-03-24  5:00 UTC (permalink / raw)
  To: LKML, linux-fsdevel, Roberto Sassu
  Cc: CIFS, Paulo Alcantara, Christian Brauner

Anyone else seeing this kernel crash in do_mknodat (I see it with a
simple "mkfifo" on smb3 mount).  I started seeing this in 6.9-rc (did
not see it in 6.8).   I did not see it with the 3/12/23 mainline
(early in the 6.9-rc merge Window) but I do see it in the 3/22 build
so it looks like the regression was introduced by:

commit 08abce60d63fb55f440c393f4508e99064f2fd91
Author: Roberto Sassu <roberto.sassu@huawei.com>
Date:   Thu Feb 15 11:31:02 2024 +0100

    security: Introduce path_post_mknod hook

    In preparation for moving IMA and EVM to the LSM infrastructure, introduce
    the path_post_mknod hook.

    IMA-appraisal requires all existing files in policy to have a file
    hash/signature stored in security.ima. An exception is made for empty files
    created by mknod, by tagging them as new files.

    LSMs could also take some action after files are created.

    The new hook cannot return an error and cannot cause the operation to be
    reverted.

Dmesg showing the crash it causes below:

[   84.862122] RIP: 0010:security_path_post_mknod+0x9/0x60
[   84.862139] Code: 41 5e 5d 31 d2 31 f6 31 ff c3 cc cc cc cc 0f 1f
00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 44 00 00 48
8b 46 30 <f6> 40 0d 02 75 43 55 48 89 e5 41 55 49 89 fd 41 54 49 89 f4
53 48
[   84.862149] RSP: 0018:ffffa22dc1f6bdc8 EFLAGS: 00010246
[   84.862159] RAX: 0000000000000000 RBX: ffff8d4fc85da000 RCX: 0000000000000000
[   84.862167] RDX: 0000000000000000 RSI: ffff8d502473a900 RDI: ffffffffaa26f6e0
[   84.862174] RBP: ffffa22dc1f6be28 R08: 0000000000000000 R09: 0000000000000000
[   84.862181] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
[   84.862187] R13: ffff8d502473a900 R14: 0000000000001000 R15: 0000000000000000
[   84.862195] FS:  00007d2c5c075800(0000) GS:ffff8d573b880000(0000)
knlGS:0000000000000000
[   84.862204] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   84.862211] CR2: 000000000000000d CR3: 000000018d63a005 CR4: 00000000003706f0
[   84.862219] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[   84.862225] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[   84.862232] Call Trace:
[   84.862238]  <TASK>
[   84.862248]  ? show_regs+0x6c/0x80
[   84.862262]  ? __die+0x24/0x80
[   84.862273]  ? page_fault_oops+0x96/0x1b0
[   84.862290]  ? do_user_addr_fault+0x30c/0x730
[   84.862304]  ? exc_page_fault+0x82/0x1b0
[   84.862318]  ? asm_exc_page_fault+0x27/0x30
[   84.862338]  ? security_path_post_mknod+0x9/0x60
[   84.862350]  ? do_mknodat+0x191/0x2c0
[   84.862365]  __x64_sys_mknodat+0x37/0x50
[   84.862376]  do_syscall_64+0x81/0x180
[   84.862387]  ? count_memcg_events.constprop.0+0x2a/0x50
[   84.862402]  ? handle_mm_fault+0xaf/0x330
[   84.862418]  ? do_user_addr_fault+0x33f/0x730
[   84.862430]  ? irqentry_exit_to_user_mode+0x6a/0x260
[   84.862442]  ? irqentry_exit+0x43/0x50
[   84.862453]  ? exc_page_fault+0x93/0x1b0
[   84.862464]  entry_SYSCALL_64_after_hwframe+0x6c/0x74
[   84.862476] RIP: 0033:0x7d2c5bf19e07
[   84.862536] Code: 9c ff ff ff e9 0a 00 00 00 66 2e 0f 1f 84 00 00
00 00 00 f3 0f 1e fa 48 89 c8 48 c1 e8 20 75 2b 41 89 ca b8 03 01 00
00 0f 05 <48> 3d 00 f0 ff ff 77 01 c3 48 8b 15 e1 3f 0e 00 f7 d8 64 89
02 b8
[   84.862544] RSP: 002b:00007ffc1b2c4568 EFLAGS: 00000246 ORIG_RAX:
0000000000000103
[   84.862556] RAX: ffffffffffffffda RBX: 00007ffc1b2c4718 RCX: 00007d2c5bf19e07
[   84.862563] RDX: 00000000000011b6 RSI: 00007ffc1b2c6712 RDI: 00000000ffffff9c
[   84.862570] RBP: 0000000000000002 R08: 0000000000000000 R09: 0000000000000000
[   84.862576] R10: 0000000000000000 R11: 0000000000000246 R12: 00007d2c5bffe428
[   84.862582] R13: 0000000000000000 R14: 00007ffc1b2c6712 R15: 00007d2c5c199000
[   84.862597]  </TASK>


--
Thanks,

Steve

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: kernel crash in mknod
  2024-03-24  5:00 kernel crash in mknod Steve French
@ 2024-03-24  5:46 ` Al Viro
  2024-03-24  6:31   ` Al Viro
  2024-03-24 16:50   ` Roberto Sassu
  0 siblings, 2 replies; 22+ messages in thread
From: Al Viro @ 2024-03-24  5:46 UTC (permalink / raw)
  To: Steve French
  Cc: LKML, linux-fsdevel, Roberto Sassu, CIFS, Paulo Alcantara,
	Christian Brauner

On Sun, Mar 24, 2024 at 12:00:15AM -0500, Steve French wrote:
> Anyone else seeing this kernel crash in do_mknodat (I see it with a
> simple "mkfifo" on smb3 mount).  I started seeing this in 6.9-rc (did
> not see it in 6.8).   I did not see it with the 3/12/23 mainline
> (early in the 6.9-rc merge Window) but I do see it in the 3/22 build
> so it looks like the regression was introduced by:

	FWIW, successful ->mknod() is allowed to return 0 and unhash
dentry, rather than bothering with lookups.  So commit in question
is bogus - lack of error does *NOT* mean that you have struct inode
existing, let alone attached to dentry.  That kind of behaviour
used to be common for network filesystems more than just for ->mknod(),
the theory being "if somebody wants to look at it, they can bloody
well pay the cost of lookup after dcache miss".

Said that, the language in D/f/vfs.rst is vague as hell and is very easy
to misread in direction of "you must instantiate".

Thankfully, there's no counterpart with mkdir - *there* it's not just
possible, it's inevitable in some cases for e.g. nfs.

What the hell is that hook doing in non-S_IFREG cases, anyway?  Move it
up and be done with it...

diff --git a/fs/namei.c b/fs/namei.c
index ceb9ddf8dfdd..821fe0e3f171 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -4050,6 +4050,8 @@ static int do_mknodat(int dfd, struct filename *name, umode_t mode,
 		case 0: case S_IFREG:
 			error = vfs_create(idmap, path.dentry->d_inode,
 					   dentry, mode, true);
+			if (!error)
+				error = security_path_post_mknod(idmap, dentry);
 			break;
 		case S_IFCHR: case S_IFBLK:
 			error = vfs_mknod(idmap, path.dentry->d_inode,
@@ -4061,10 +4063,6 @@ static int do_mknodat(int dfd, struct filename *name, umode_t mode,
 			break;
 	}
 
-	if (error)
-		goto out2;
-
-	security_path_post_mknod(idmap, dentry);
 out2:
 	done_path_create(&path, dentry);
 	if (retry_estale(error, lookup_flags)) {

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: kernel crash in mknod
  2024-03-24  5:46 ` Al Viro
@ 2024-03-24  6:31   ` Al Viro
  2024-03-24 16:50   ` Roberto Sassu
  1 sibling, 0 replies; 22+ messages in thread
From: Al Viro @ 2024-03-24  6:31 UTC (permalink / raw)
  To: Steve French
  Cc: LKML, linux-fsdevel, Roberto Sassu, CIFS, Paulo Alcantara,
	Christian Brauner

On Sun, Mar 24, 2024 at 05:46:36AM +0000, Al Viro wrote:
> On Sun, Mar 24, 2024 at 12:00:15AM -0500, Steve French wrote:
> > Anyone else seeing this kernel crash in do_mknodat (I see it with a
> > simple "mkfifo" on smb3 mount).  I started seeing this in 6.9-rc (did
> > not see it in 6.8).   I did not see it with the 3/12/23 mainline
> > (early in the 6.9-rc merge Window) but I do see it in the 3/22 build
> > so it looks like the regression was introduced by:
> 
> 	FWIW, successful ->mknod() is allowed to return 0 and unhash
> dentry, rather than bothering with lookups.  So commit in question
> is bogus - lack of error does *NOT* mean that you have struct inode
> existing, let alone attached to dentry.  That kind of behaviour
> used to be common for network filesystems more than just for ->mknod(),
> the theory being "if somebody wants to look at it, they can bloody
> well pay the cost of lookup after dcache miss".
> 
> Said that, the language in D/f/vfs.rst is vague as hell and is very easy
> to misread in direction of "you must instantiate".
> 
> Thankfully, there's no counterpart with mkdir - *there* it's not just
> possible, it's inevitable in some cases for e.g. nfs.
> 
> What the hell is that hook doing in non-S_IFREG cases, anyway?  Move it
> up and be done with it...

PS: moving the call site up to S_IFREG case deals with the immediate
problem (->create() *IS* required to make dentry uptodate), but the other
side of what had lead to that bug needs to be dealt with separately.

It needs to be documented clearly (for all object-creating methods) and
we need to decide what their behaviours should be.  Right now it's
	successful ->create() must make positive
	successful ->mkdir() may leave negative unhashed (and it might be forced to)
	successful ->tmpfile() must make positive
->mknod() and ->symlink() are uncertain.  VFS doesn't give a damn;
other users might.  FWIW, ecryptfs is fine with either behaviour.
nfsd and overlayfs might or might not break.  AF_UNIX bind()
probably *does* break on such ->mknod() behaviour and unless I'm
misreading the history it had been that way since way back.

From a quick look through ->mknod() instances it looks like
CIFS_MOUNT_UNX_EMUL case in cifs is the odd man out at the moment.

Could you check it AF_UNIX bind() with ->sun_path containing
a pathname that resolves to (inexistent) file on your filesystem
breaks with your setup?
setup?

^ permalink raw reply	[flat|nested] 22+ messages in thread

* RE: kernel crash in mknod
  2024-03-24  5:46 ` Al Viro
  2024-03-24  6:31   ` Al Viro
@ 2024-03-24 16:50   ` Roberto Sassu
  2024-03-24 21:02     ` Al Viro
                       ` (2 more replies)
  1 sibling, 3 replies; 22+ messages in thread
From: Roberto Sassu @ 2024-03-24 16:50 UTC (permalink / raw)
  To: Al Viro, Steve French
  Cc: LKML, linux-fsdevel, CIFS, Paulo Alcantara, Christian Brauner,
	Mimi Zohar, Paul Moore, linux-integrity, linux-security-module

> From: Al Viro [mailto:viro@ftp.linux.org.uk] On Behalf Of Al Viro
> Sent: Sunday, March 24, 2024 6:47 AM
> On Sun, Mar 24, 2024 at 12:00:15AM -0500, Steve French wrote:
> > Anyone else seeing this kernel crash in do_mknodat (I see it with a
> > simple "mkfifo" on smb3 mount).  I started seeing this in 6.9-rc (did
> > not see it in 6.8).   I did not see it with the 3/12/23 mainline
> > (early in the 6.9-rc merge Window) but I do see it in the 3/22 build
> > so it looks like the regression was introduced by:
> 
> 	FWIW, successful ->mknod() is allowed to return 0 and unhash
> dentry, rather than bothering with lookups.  So commit in question
> is bogus - lack of error does *NOT* mean that you have struct inode
> existing, let alone attached to dentry.  That kind of behaviour
> used to be common for network filesystems more than just for ->mknod(),
> the theory being "if somebody wants to look at it, they can bloody
> well pay the cost of lookup after dcache miss".
> 
> Said that, the language in D/f/vfs.rst is vague as hell and is very easy
> to misread in direction of "you must instantiate".
> 
> Thankfully, there's no counterpart with mkdir - *there* it's not just
> possible, it's inevitable in some cases for e.g. nfs.
> 
> What the hell is that hook doing in non-S_IFREG cases, anyway?  Move it
> up and be done with it...

Hi Al

thanks for the patch. Indeed, it was like that before, when instead of
an LSM hook there was an IMA call.

However, I thought, since we were promoting it as an LSM hook,
we should be as generic possible, and support more usages than
what was needed for IMA.

> diff --git a/fs/namei.c b/fs/namei.c
> index ceb9ddf8dfdd..821fe0e3f171 100644
> --- a/fs/namei.c
> +++ b/fs/namei.c
> @@ -4050,6 +4050,8 @@ static int do_mknodat(int dfd, struct filename *name, umode_t mode,
>  		case 0: case S_IFREG:
>  			error = vfs_create(idmap, path.dentry->d_inode,
>  					   dentry, mode, true);
> +			if (!error)
> +				error = security_path_post_mknod(idmap, dentry);

Minor issue, security_path_post_mknod() does not return an error.

Also, please update the description of security_path_post_mknod() to say
that it is not going to be called for non-regular files.

Hopefully, Paul also agrees with this change.

Other than that, please add my:

Reviewed-by: Roberto Sassu <roberto.sassu@huawei.com>

Thanks

Roberto

>  			break;
>  		case S_IFCHR: case S_IFBLK:
>  			error = vfs_mknod(idmap, path.dentry->d_inode,
> @@ -4061,10 +4063,6 @@ static int do_mknodat(int dfd, struct filename *name, umode_t mode,
>  			break;
>  	}
> 
> -	if (error)
> -		goto out2;
> -
> -	security_path_post_mknod(idmap, dentry);
>  out2:
>  	done_path_create(&path, dentry);
>  	if (retry_estale(error, lookup_flags)) {

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: kernel crash in mknod
  2024-03-24 16:50   ` Roberto Sassu
@ 2024-03-24 21:02     ` Al Viro
  2024-03-25 16:06     ` Christian Brauner
  2024-03-25 17:05     ` Paul Moore
  2 siblings, 0 replies; 22+ messages in thread
From: Al Viro @ 2024-03-24 21:02 UTC (permalink / raw)
  To: Roberto Sassu
  Cc: Steve French, LKML, linux-fsdevel, CIFS, Paulo Alcantara,
	Christian Brauner, Mimi Zohar, Paul Moore, linux-integrity,
	linux-security-module

On Sun, Mar 24, 2024 at 04:50:24PM +0000, Roberto Sassu wrote:

> Also, please update the description of security_path_post_mknod() to say
> that it is not going to be called for non-regular files.

If anything, it's rather security_past_create_without_open(), and
I really wonder where does the equivalent of those actions happen
if you do close(open("foo", O_CREAT|O_RDWR, 0777)) instead of
mknod("foo", 0777, 0).  I mean, you can substitute the former
for the latter, so anything that must be done by the hook in
mknod(2) would better be covered at some point in hooks within
open(2)...  Some explanation of the relationship between those
would be nice.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: kernel crash in mknod
  2024-03-24 16:50   ` Roberto Sassu
  2024-03-24 21:02     ` Al Viro
@ 2024-03-25 16:06     ` Christian Brauner
  2024-03-25 17:18       ` Roberto Sassu
                         ` (2 more replies)
  2024-03-25 17:05     ` Paul Moore
  2 siblings, 3 replies; 22+ messages in thread
From: Christian Brauner @ 2024-03-25 16:06 UTC (permalink / raw)
  To: Roberto Sassu
  Cc: Al Viro, Steve French, LKML, linux-fsdevel, CIFS,
	Paulo Alcantara, Christian Brauner, Mimi Zohar, Paul Moore,
	linux-integrity, linux-security-module

On Sun, Mar 24, 2024 at 04:50:24PM +0000, Roberto Sassu wrote:
> > From: Al Viro [mailto:viro@ftp.linux.org.uk] On Behalf Of Al Viro
> > Sent: Sunday, March 24, 2024 6:47 AM
> > On Sun, Mar 24, 2024 at 12:00:15AM -0500, Steve French wrote:
> > > Anyone else seeing this kernel crash in do_mknodat (I see it with a
> > > simple "mkfifo" on smb3 mount).  I started seeing this in 6.9-rc (did
> > > not see it in 6.8).   I did not see it with the 3/12/23 mainline
> > > (early in the 6.9-rc merge Window) but I do see it in the 3/22 build
> > > so it looks like the regression was introduced by:
> > 
> > 	FWIW, successful ->mknod() is allowed to return 0 and unhash
> > dentry, rather than bothering with lookups.  So commit in question
> > is bogus - lack of error does *NOT* mean that you have struct inode
> > existing, let alone attached to dentry.  That kind of behaviour
> > used to be common for network filesystems more than just for ->mknod(),
> > the theory being "if somebody wants to look at it, they can bloody
> > well pay the cost of lookup after dcache miss".
> > 
> > Said that, the language in D/f/vfs.rst is vague as hell and is very easy
> > to misread in direction of "you must instantiate".
> > 
> > Thankfully, there's no counterpart with mkdir - *there* it's not just
> > possible, it's inevitable in some cases for e.g. nfs.
> > 
> > What the hell is that hook doing in non-S_IFREG cases, anyway?  Move it
> > up and be done with it...
> 
> Hi Al
> 
> thanks for the patch. Indeed, it was like that before, when instead of
> an LSM hook there was an IMA call.

Could you please start adding lore links into your commit messages for
all messages that are sent to a mailing list? It really makes tracking
down the original thread a lot easier.

> However, I thought, since we were promoting it as an LSM hook,
> we should be as generic possible, and support more usages than
> what was needed for IMA.

I'm a bit confused now why this is taking a dentry. Nothing in IMA or
EVM cares about the dentry for these hooks so it really should have take
an inode in the first place?

And one minor other question I just realized. Why are some of the new
hooks called security_path_post_mknod() when they aren't actually taking
a path in contrast to say
security_path_{chown,chmod,mknod,chroot,truncate}() that do.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: kernel crash in mknod
  2024-03-24 16:50   ` Roberto Sassu
  2024-03-24 21:02     ` Al Viro
  2024-03-25 16:06     ` Christian Brauner
@ 2024-03-25 17:05     ` Paul Moore
  2 siblings, 0 replies; 22+ messages in thread
From: Paul Moore @ 2024-03-25 17:05 UTC (permalink / raw)
  To: Roberto Sassu
  Cc: Al Viro, Steve French, LKML, linux-fsdevel, CIFS,
	Paulo Alcantara, Christian Brauner, Mimi Zohar, linux-integrity,
	linux-security-module

On Sun, Mar 24, 2024 at 12:50 PM Roberto Sassu <roberto.sassu@huawei.com> wrote:
> > From: Al Viro [mailto:viro@ftp.linux.org.uk] On Behalf Of Al Viro
> > Sent: Sunday, March 24, 2024 6:47 AM
> > On Sun, Mar 24, 2024 at 12:00:15AM -0500, Steve French wrote:
> > > Anyone else seeing this kernel crash in do_mknodat (I see it with a
> > > simple "mkfifo" on smb3 mount).  I started seeing this in 6.9-rc (did
> > > not see it in 6.8).   I did not see it with the 3/12/23 mainline
> > > (early in the 6.9-rc merge Window) but I do see it in the 3/22 build
> > > so it looks like the regression was introduced by:
> >
> >       FWIW, successful ->mknod() is allowed to return 0 and unhash
> > dentry, rather than bothering with lookups.  So commit in question
> > is bogus - lack of error does *NOT* mean that you have struct inode
> > existing, let alone attached to dentry.  That kind of behaviour
> > used to be common for network filesystems more than just for ->mknod(),
> > the theory being "if somebody wants to look at it, they can bloody
> > well pay the cost of lookup after dcache miss".
> >
> > Said that, the language in D/f/vfs.rst is vague as hell and is very easy
> > to misread in direction of "you must instantiate".
> >
> > Thankfully, there's no counterpart with mkdir - *there* it's not just
> > possible, it's inevitable in some cases for e.g. nfs.
> >
> > What the hell is that hook doing in non-S_IFREG cases, anyway?  Move it
> > up and be done with it...
>
> Hi Al
>
> thanks for the patch. Indeed, it was like that before, when instead of
> an LSM hook there was an IMA call.
>
> However, I thought, since we were promoting it as an LSM hook,
> we should be as generic possible, and support more usages than
> what was needed for IMA.
>
> > diff --git a/fs/namei.c b/fs/namei.c
> > index ceb9ddf8dfdd..821fe0e3f171 100644
> > --- a/fs/namei.c
> > +++ b/fs/namei.c
> > @@ -4050,6 +4050,8 @@ static int do_mknodat(int dfd, struct filename *name, umode_t mode,
> >               case 0: case S_IFREG:
> >                       error = vfs_create(idmap, path.dentry->d_inode,
> >                                          dentry, mode, true);
> > +                     if (!error)
> > +                             error = security_path_post_mknod(idmap, dentry);
>
> Minor issue, security_path_post_mknod() does not return an error.
>
> Also, please update the description of security_path_post_mknod() to say
> that it is not going to be called for non-regular files.
>
> Hopefully, Paul also agrees with this change.
>
> Other than that, please add my:
>
> Reviewed-by: Roberto Sassu <roberto.sassu@huawei.com>

No objections here for obvious reasons.

Acked-by: Paul Moore <paul@paul-moore.com>

-- 
paul-moore.com

^ permalink raw reply	[flat|nested] 22+ messages in thread

* RE: kernel crash in mknod
  2024-03-25 16:06     ` Christian Brauner
@ 2024-03-25 17:18       ` Roberto Sassu
  2024-03-26 11:40         ` Christian Brauner
  2024-03-25 17:21       ` Paul Moore
       [not found]       ` <CAH2r5muL4NEwLxq_qnPOCTHunLB_vmDA-1jJ152POwBv+aTcXg@mail.gmail.com>
  2 siblings, 1 reply; 22+ messages in thread
From: Roberto Sassu @ 2024-03-25 17:18 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Al Viro, Steve French, LKML, linux-fsdevel, CIFS,
	Paulo Alcantara, Christian Brauner, Mimi Zohar, Paul Moore,
	linux-integrity, linux-security-module

> From: Christian Brauner [mailto:brauner@kernel.org]
> Sent: Monday, March 25, 2024 5:06 PM
> On Sun, Mar 24, 2024 at 04:50:24PM +0000, Roberto Sassu wrote:
> > > From: Al Viro [mailto:viro@ftp.linux.org.uk] On Behalf Of Al Viro
> > > Sent: Sunday, March 24, 2024 6:47 AM
> > > On Sun, Mar 24, 2024 at 12:00:15AM -0500, Steve French wrote:
> > > > Anyone else seeing this kernel crash in do_mknodat (I see it with a
> > > > simple "mkfifo" on smb3 mount).  I started seeing this in 6.9-rc (did
> > > > not see it in 6.8).   I did not see it with the 3/12/23 mainline
> > > > (early in the 6.9-rc merge Window) but I do see it in the 3/22 build
> > > > so it looks like the regression was introduced by:
> > >
> > > 	FWIW, successful ->mknod() is allowed to return 0 and unhash
> > > dentry, rather than bothering with lookups.  So commit in question
> > > is bogus - lack of error does *NOT* mean that you have struct inode
> > > existing, let alone attached to dentry.  That kind of behaviour
> > > used to be common for network filesystems more than just for ->mknod(),
> > > the theory being "if somebody wants to look at it, they can bloody
> > > well pay the cost of lookup after dcache miss".
> > >
> > > Said that, the language in D/f/vfs.rst is vague as hell and is very easy
> > > to misread in direction of "you must instantiate".
> > >
> > > Thankfully, there's no counterpart with mkdir - *there* it's not just
> > > possible, it's inevitable in some cases for e.g. nfs.
> > >
> > > What the hell is that hook doing in non-S_IFREG cases, anyway?  Move it
> > > up and be done with it...
> >
> > Hi Al
> >
> > thanks for the patch. Indeed, it was like that before, when instead of
> > an LSM hook there was an IMA call.
> 
> Could you please start adding lore links into your commit messages for
> all messages that are sent to a mailing list? It really makes tracking
> down the original thread a lot easier.

Sure, will do next time.

> > However, I thought, since we were promoting it as an LSM hook,
> > we should be as generic possible, and support more usages than
> > what was needed for IMA.
> 
> I'm a bit confused now why this is taking a dentry. Nothing in IMA or
> EVM cares about the dentry for these hooks so it really should have take
> an inode in the first place?

Uhm, you are right. Does that mean that instead of what Al proposed,
we can change the parameter of security_path_post_mknod() from
dentry to inode?

> And one minor other question I just realized. Why are some of the new
> hooks called security_path_post_mknod() when they aren't actually taking
> a path in contrast to say
> security_path_{chown,chmod,mknod,chroot,truncate}() that do.

I would agree to any change that makes this more consistent, as long as
IMA has access to the new inode.

Roberto

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: kernel crash in mknod
  2024-03-25 16:06     ` Christian Brauner
  2024-03-25 17:18       ` Roberto Sassu
@ 2024-03-25 17:21       ` Paul Moore
       [not found]       ` <CAH2r5muL4NEwLxq_qnPOCTHunLB_vmDA-1jJ152POwBv+aTcXg@mail.gmail.com>
  2 siblings, 0 replies; 22+ messages in thread
From: Paul Moore @ 2024-03-25 17:21 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Roberto Sassu, Al Viro, Steve French, LKML, linux-fsdevel, CIFS,
	Paulo Alcantara, Christian Brauner, Mimi Zohar, linux-integrity,
	linux-security-module

On Mon, Mar 25, 2024 at 12:06 PM Christian Brauner <brauner@kernel.org> wrote:
> I'm a bit confused now why this is taking a dentry. Nothing in IMA or
> EVM cares about the dentry for these hooks so it really should have take
> an inode in the first place?

I don't want to speak for Roberto or Mimi here, but this LSM hook was
intended to replace the dedicated ima_post_path_mknod() hook as I
wanted to see IMA/EVM integrated as proper LSMs so we could so away
with all of the special IMA/EVM hooks and treat everything as a LSM.
Part of this was creating new LSM hooks where historically we only had
a IMA and/or EVM hook, the security_path_post_mknod() hook is such a
case (e.g. /ima_post_path_mknod/security_path_post_mknod/) and the new
LSM hook kept the same parameters as the old IMA hook.

Yes, you are correct that neither IMA and EVM do anything with the
dentry other than looking at the associated inode.  I'm not the
IMA/EVM expert in this thread, but I suspect this is simply an old
vestige of former code, or perhaps an "optimization" to avoid having
to fetch the inode pointer in cases where IMA/EVM was not enabled
(although it is used in the vfs_create() call directly above, so who
knows ...

> And one minor other question I just realized. Why are some of the new
> hooks called security_path_post_mknod() when they aren't actually taking
> a path in contrast to say
> security_path_{chown,chmod,mknod,chroot,truncate}() that do.

Once again, think of this as a
/ima_post_path_mknod/security_path_post_mknod/ type of replacement and
you have your answer.  That said, I'm not really against bikeshedding
LSM hook names if people want to do that, it's not a stable protected
API so while we try to keep it stable~ish simply for our own sanity,
I'm happy to see it changed if everyone agrees it makes sense.

-- 
paul-moore.com

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: kernel crash in mknod
       [not found]       ` <CAH2r5muL4NEwLxq_qnPOCTHunLB_vmDA-1jJ152POwBv+aTcXg@mail.gmail.com>
@ 2024-03-25 19:54         ` Al Viro
  2024-03-25 20:46           ` Al Viro
  2024-03-25 20:47           ` Paulo Alcantara
  0 siblings, 2 replies; 22+ messages in thread
From: Al Viro @ 2024-03-25 19:54 UTC (permalink / raw)
  To: Steve French
  Cc: Christian Brauner, Roberto Sassu, LKML, linux-fsdevel, CIFS,
	Paulo Alcantara, Christian Brauner, Mimi Zohar, Paul Moore,
	linux-integrity, linux-security-module

On Mon, Mar 25, 2024 at 11:26:59AM -0500, Steve French wrote:

> A loosely related question.  Do I need to change cifs.ko to return the
> pointer to inode on mknod now?  dentry->inode is NULL in the case of mknod
> from cifs.ko (and presumably some other fs as Al noted), unlike mkdir and
> create where it is filled in.   Is there a perf advantage in filling in the
> dentry->inode in the mknod path in the fs or better to leave it as is?  Is
> there a good example to borrow from on this?

AFAICS, that case in in CIFS is the only instance of ->mknod() that does this
"skip lookups, just unhash and return 0" at the moment.

What's more, it really had been broken all along for one important case -
AF_UNIX bind(2) with address (== socket pathname) being on the filesystem
in question.

Options:
	1) make vfs_mknod() callers aware of the possibility, have the ones
that care do lookup in case when return value is 0 and dentry is unhashed.
That's similar to what we do for vfs_mkdir().  No changes needed for CIFS
or fs/namei.c (i.e. do_mknodat()), unix_bind() definitely needs a change,
ecryptfs can stay as-is, overlayfs just needs to stop complaining when it sees
that situation, nfsd might or might not need a change - hadn't checked yet.
In that case we document ->mknod() as "may unhash and return 0 if it wants
to save a lookup".
	2) make vfs_mknod() check for that case and have it call ->lookup()
if it sees that.  I don't see any benefits to that, TBH - no performance
benefits anywhere and no real simplification for ->mknod() instances.  It
does avoid the need to change anything in CIFS, though.
	3) require ->mknod() instances to make dentry positive on success.
CIFS needs a fix, documentation gets updated to explicitly require that.
AFAICS, nothing else would need to be touched, except possibly adding
a warning in vfs_mknod() to catch violation of that rule.

Note that cifs_sfu_make_node() is the only case in CIFS where that happens -
other codepaths (both in cifs_make_node() and in smb2_make_node()) will
instantiate.  How painful would it be for cifs_sfu_make_node()?
AFAICS, you do open/sync_write/close there; would it be hard to do
an eqiuvalent of fstat and set the inode up?  No need to reread the
file contents (as cifs_sfu_type() does), and you do have full path
anyway, so it's less work than for full ->lookup() even if you need
a path-based protocol operations...

Does that thing have an equivalent of fstat() that would return the
metadata of opened file?

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: kernel crash in mknod
  2024-03-25 19:54         ` Al Viro
@ 2024-03-25 20:46           ` Al Viro
  2024-03-25 20:47           ` Paulo Alcantara
  1 sibling, 0 replies; 22+ messages in thread
From: Al Viro @ 2024-03-25 20:46 UTC (permalink / raw)
  To: Steve French
  Cc: Christian Brauner, Roberto Sassu, LKML, linux-fsdevel, CIFS,
	Paulo Alcantara, Christian Brauner, Mimi Zohar, Paul Moore,
	linux-integrity, linux-security-module

On Mon, Mar 25, 2024 at 07:54:13PM +0000, Al Viro wrote:

> Note that cifs_sfu_make_node() is the only case in CIFS where that happens -
> other codepaths (both in cifs_make_node() and in smb2_make_node()) will
> instantiate.  How painful would it be for cifs_sfu_make_node()?
> AFAICS, you do open/sync_write/close there; would it be hard to do
> an eqiuvalent of fstat and set the inode up?  No need to reread the
> file contents (as cifs_sfu_type() does), and you do have full path
> anyway, so it's less work than for full ->lookup() even if you need
> a path-based protocol operations...
> 
> Does that thing have an equivalent of fstat() that would return the
> metadata of opened file?

You do have a FID there, so doing ->query_file_info() just before close,
using the result to build inode (with type and ->i_rdev taken from what
you've been given by the caller) and passing it to d_instantiate() looks
not entirely implausible, but I'm really not familiar with the codebase,
so take that with a cartload of salt.

mknod() usually is followed by lookup of some sort pretty soon, and your
lookup would have to do at least open/sync_read/close just to decode the
device number.  So if anything, *not* setting an inode up during mknod()
is likely to be a pessimization...

If we did it in vfs_mknod() callers, that would be something along the
lines of
	err = vfs_mknod(..., dir, dentry, ...)
	if (err)
		fuck off
	if (unlikely(!dentry->d_inode)) {
		if (d_unhashed(dentry)) {
			struct dentry *d = dir->i_op->lookup(dir, dentry, 0);
			if (unlikely(d)) {
				if (IS_ERR(d)) {
					fuck off, lookup failed
				} else {
					// ->lookup returns a pointer to existing
					// alias *ONLY* for directories; WTF is
					// going on?
					dput(d);
					fuck off, wrong thing created there
				}
			}
			if (!dentry->d_inode)
				fuck off, it hasn't been created
			if (wrong type of dentry->d_inode))
				fuck off, wrong thing created there
			OK, there we go
		} else {
			complain about bogus ->mknod() behavior
			fuck off - it hasn't been created, apparently
		}
	}
at least in net/unix/af_unix.c:unix_bind().  So the minimal change
would be to have your d_drop(dentry) in that codepath followed by
cifs_lookup(<parent inode>, dentry, 0) and checking the result.

But I would very much suspect that fetching metadata by fid before
you close the file would be cheaper than full-blown cifs_lookup()
there.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: kernel crash in mknod
  2024-03-25 19:54         ` Al Viro
  2024-03-25 20:46           ` Al Viro
@ 2024-03-25 20:47           ` Paulo Alcantara
  2024-03-25 21:13             ` Al Viro
  1 sibling, 1 reply; 22+ messages in thread
From: Paulo Alcantara @ 2024-03-25 20:47 UTC (permalink / raw)
  To: Al Viro, Steve French
  Cc: Christian Brauner, Roberto Sassu, LKML, linux-fsdevel, CIFS,
	Christian Brauner, Mimi Zohar, Paul Moore, linux-integrity,
	linux-security-module

Al Viro <viro@zeniv.linux.org.uk> writes:

> On Mon, Mar 25, 2024 at 11:26:59AM -0500, Steve French wrote:
>
>> A loosely related question.  Do I need to change cifs.ko to return the
>> pointer to inode on mknod now?  dentry->inode is NULL in the case of mknod
>> from cifs.ko (and presumably some other fs as Al noted), unlike mkdir and
>> create where it is filled in.   Is there a perf advantage in filling in the
>> dentry->inode in the mknod path in the fs or better to leave it as is?  Is
>> there a good example to borrow from on this?
>
> AFAICS, that case in in CIFS is the only instance of ->mknod() that does this
> "skip lookups, just unhash and return 0" at the moment.
>
> What's more, it really had been broken all along for one important case -
> AF_UNIX bind(2) with address (== socket pathname) being on the filesystem
> in question.

Yes, except that we currently return -EPERM for such cases.  I don't
even know if this SFU thing supports sockets.

> Note that cifs_sfu_make_node() is the only case in CIFS where that happens -
> other codepaths (both in cifs_make_node() and in smb2_make_node()) will
> instantiate.  How painful would it be for cifs_sfu_make_node()?
> AFAICS, you do open/sync_write/close there; would it be hard to do
> an eqiuvalent of fstat and set the inode up?

This should be pretty straightforward as it would only require an extra
query info call and then {smb311_posix,cifs}_get_inode_info() ->
d_instantiate().  We could even make it a single compound request of
open/write/getinfo/close for SMB2+ case.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: kernel crash in mknod
  2024-03-25 20:47           ` Paulo Alcantara
@ 2024-03-25 21:13             ` Al Viro
  2024-03-25 21:31               ` Paulo Alcantara
  0 siblings, 1 reply; 22+ messages in thread
From: Al Viro @ 2024-03-25 21:13 UTC (permalink / raw)
  To: Paulo Alcantara
  Cc: Steve French, Christian Brauner, Roberto Sassu, LKML,
	linux-fsdevel, CIFS, Christian Brauner, Mimi Zohar, Paul Moore,
	linux-integrity, linux-security-module

On Mon, Mar 25, 2024 at 05:47:16PM -0300, Paulo Alcantara wrote:
> Al Viro <viro@zeniv.linux.org.uk> writes:
> 
> > On Mon, Mar 25, 2024 at 11:26:59AM -0500, Steve French wrote:
> >
> >> A loosely related question.  Do I need to change cifs.ko to return the
> >> pointer to inode on mknod now?  dentry->inode is NULL in the case of mknod
> >> from cifs.ko (and presumably some other fs as Al noted), unlike mkdir and
> >> create where it is filled in.   Is there a perf advantage in filling in the
> >> dentry->inode in the mknod path in the fs or better to leave it as is?  Is
> >> there a good example to borrow from on this?
> >
> > AFAICS, that case in in CIFS is the only instance of ->mknod() that does this
> > "skip lookups, just unhash and return 0" at the moment.
> >
> > What's more, it really had been broken all along for one important case -
> > AF_UNIX bind(2) with address (== socket pathname) being on the filesystem
> > in question.
> 
> Yes, except that we currently return -EPERM for such cases.  I don't
> even know if this SFU thing supports sockets.

	Sure, but we really want the rules to be reasonably simple and
"you may leave dentry unhashed negative and return 0, provided that you
hadn't been asked to create a socket" is anything but ;-)

> > Note that cifs_sfu_make_node() is the only case in CIFS where that happens -
> > other codepaths (both in cifs_make_node() and in smb2_make_node()) will
> > instantiate.  How painful would it be for cifs_sfu_make_node()?
> > AFAICS, you do open/sync_write/close there; would it be hard to do
> > an eqiuvalent of fstat and set the inode up?
> 
> This should be pretty straightforward as it would only require an extra
> query info call and then {smb311_posix,cifs}_get_inode_info() ->
> d_instantiate().  We could even make it a single compound request of
> open/write/getinfo/close for SMB2+ case.

	If that's the case, I believe that we should simply declare that
->mknod() must instantiate on success and have vfs_mknod() check and
warn if it hadn't.

	Rationale:

1) mknod(2) is usually followed by at least some access to created object.
Not setting the inode up won't save much anyway.
2) if some instance of ->mknod() skips setting the inode on success (i.e.
unhashes the still-negative dentry and returns 0), it can easily be
converted.  The minimal conversion would be along the lines of turning
	d_drop(dentry);
	return 0;
into
	d_drop(dentry);
	d = foofs_lookup(dir, dentry, 0);
	if (unlikely(d)) {
		if (!IS_ERR(d)) {
			dput(d);
			return -EINVAL;	// weird shit - directory got created somehow
		}
		return PTR_ERR(d);
	}
	return 0;
but there almost certainly are cheaper ways to get the inode metadata,
set the inode up and instantiate the dentry.
3) currently only on in-kernel instance is that way.
4) it makes life simpler for the users of vfs_mknod().

	Objections, anyone?

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: kernel crash in mknod
  2024-03-25 21:13             ` Al Viro
@ 2024-03-25 21:31               ` Paulo Alcantara
  0 siblings, 0 replies; 22+ messages in thread
From: Paulo Alcantara @ 2024-03-25 21:31 UTC (permalink / raw)
  To: Al Viro, Steve French
  Cc: Christian Brauner, Roberto Sassu, LKML, linux-fsdevel, CIFS,
	Christian Brauner, Mimi Zohar, Paul Moore, linux-integrity,
	linux-security-module

Al Viro <viro@zeniv.linux.org.uk> writes:

> On Mon, Mar 25, 2024 at 05:47:16PM -0300, Paulo Alcantara wrote:
>> Al Viro <viro@zeniv.linux.org.uk> writes:
>> 
>> > On Mon, Mar 25, 2024 at 11:26:59AM -0500, Steve French wrote:
>> >
>> >> A loosely related question.  Do I need to change cifs.ko to return the
>> >> pointer to inode on mknod now?  dentry->inode is NULL in the case of mknod
>> >> from cifs.ko (and presumably some other fs as Al noted), unlike mkdir and
>> >> create where it is filled in.   Is there a perf advantage in filling in the
>> >> dentry->inode in the mknod path in the fs or better to leave it as is?  Is
>> >> there a good example to borrow from on this?
>> >
>> > AFAICS, that case in in CIFS is the only instance of ->mknod() that does this
>> > "skip lookups, just unhash and return 0" at the moment.
>> >
>> > What's more, it really had been broken all along for one important case -
>> > AF_UNIX bind(2) with address (== socket pathname) being on the filesystem
>> > in question.
>> 
>> Yes, except that we currently return -EPERM for such cases.  I don't
>> even know if this SFU thing supports sockets.
>
> 	Sure, but we really want the rules to be reasonably simple and
> "you may leave dentry unhashed negative and return 0, provided that you
> hadn't been asked to create a socket" is anything but ;-)

Agreed :-)

>> > Note that cifs_sfu_make_node() is the only case in CIFS where that happens -
>> > other codepaths (both in cifs_make_node() and in smb2_make_node()) will
>> > instantiate.  How painful would it be for cifs_sfu_make_node()?
>> > AFAICS, you do open/sync_write/close there; would it be hard to do
>> > an eqiuvalent of fstat and set the inode up?
>> 
>> This should be pretty straightforward as it would only require an extra
>> query info call and then {smb311_posix,cifs}_get_inode_info() ->
>> d_instantiate().  We could even make it a single compound request of
>> open/write/getinfo/close for SMB2+ case.
>
> 	If that's the case, I believe that we should simply declare that
> ->mknod() must instantiate on success and have vfs_mknod() check and
> warn if it hadn't.

LGTM.

Steve, any objections?

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: kernel crash in mknod
  2024-03-25 17:18       ` Roberto Sassu
@ 2024-03-26 11:40         ` Christian Brauner
  2024-03-26 12:53           ` Paul Moore
  2024-03-28 10:53           ` Roberto Sassu
  0 siblings, 2 replies; 22+ messages in thread
From: Christian Brauner @ 2024-03-26 11:40 UTC (permalink / raw)
  To: Roberto Sassu
  Cc: Al Viro, Steve French, LKML, linux-fsdevel, CIFS,
	Paulo Alcantara, Christian Brauner, Mimi Zohar, Paul Moore,
	linux-integrity, linux-security-module

> we can change the parameter of security_path_post_mknod() from
> dentry to inode?

If all current callers only operate on the inode then it seems the best
to only pass the inode. If there's some reason someone later needs a
dentry the hook can always be changed.

For bigger changes it's also worthwhile if the object that's passed down
into the hook-based LSM layer is as specific as possible. If someone
does a change that affects lifetime rules of mounts then any hook that
takes a struct path argument that's unused means going through each LSM
that implements the hook only to find out it's not actually used.
Similar for dentry vs inode imho.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: kernel crash in mknod
  2024-03-26 11:40         ` Christian Brauner
@ 2024-03-26 12:53           ` Paul Moore
  2024-03-28 10:53           ` Roberto Sassu
  1 sibling, 0 replies; 22+ messages in thread
From: Paul Moore @ 2024-03-26 12:53 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Roberto Sassu, Al Viro, Steve French, LKML, linux-fsdevel, CIFS,
	Paulo Alcantara, Christian Brauner, Mimi Zohar, linux-integrity,
	linux-security-module

On Tue, Mar 26, 2024 at 7:40 AM Christian Brauner <brauner@kernel.org> wrote:
>
> For bigger changes it's also worthwhile if the object that's passed down
> into the hook-based LSM layer is as specific as possible. If someone
> does a change that affects lifetime rules of mounts then any hook that
> takes a struct path argument that's unused means going through each LSM
> that implements the hook only to find out it's not actually used.
> Similar for dentry vs inode imho.

For bigger changes please always ensure that the LSM list, and any
related LSM implementation lists, are on the To/CC line.  While we
appreciate Christian's input (and Al's, and all the other VFS devs) on
VFS matters, there are often other considerations that need to be
taken into account when discussing LSM related issues.  Generally,
"specific as possible" is good input, but it isn't the only thing we
need to worry about, and sometimes other requirements mean that it
isn't the best choice.  Just as we want the VFS devs involved in
discussions about VFS related LSM hooks (these new IMA/EVM-related LSM
hooks were sent to, and reviewed by the VFS folks), I would hope the
VFS devs would want to include the LSM devs on any LSM related issues
and would try to avoid speaking on behalf of the LSM devs and
maintainers.

-- 
paul-moore.com

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: kernel crash in mknod
  2024-03-26 11:40         ` Christian Brauner
  2024-03-26 12:53           ` Paul Moore
@ 2024-03-28 10:53           ` Roberto Sassu
  2024-03-28 11:08             ` Christian Brauner
  1 sibling, 1 reply; 22+ messages in thread
From: Roberto Sassu @ 2024-03-28 10:53 UTC (permalink / raw)
  To: Christian Brauner, Roberto Sassu
  Cc: Al Viro, Steve French, LKML, linux-fsdevel, CIFS,
	Paulo Alcantara, Christian Brauner, Mimi Zohar, Paul Moore,
	linux-integrity, linux-security-module

On 3/26/2024 12:40 PM, Christian Brauner wrote:
>> we can change the parameter of security_path_post_mknod() from
>> dentry to inode?
> 
> If all current callers only operate on the inode then it seems the best
> to only pass the inode. If there's some reason someone later needs a
> dentry the hook can always be changed.

Ok, so the crash is likely caused by:

void security_path_post_mknod(struct mnt_idmap *idmap, struct dentry 
*dentry)
{
         if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))

I guess we can also simply check if there is an inode attached to the 
dentry, to minimize the changes. I can do both.

More technical question, do I need to do extra checks on the dentry 
before calling security_path_post_mknod()?

Thanks

Roberto

> For bigger changes it's also worthwhile if the object that's passed down
> into the hook-based LSM layer is as specific as possible. If someone
> does a change that affects lifetime rules of mounts then any hook that
> takes a struct path argument that's unused means going through each LSM
> that implements the hook only to find out it's not actually used.
> Similar for dentry vs inode imho.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: kernel crash in mknod
  2024-03-28 10:53           ` Roberto Sassu
@ 2024-03-28 11:08             ` Christian Brauner
  2024-03-28 11:24               ` Roberto Sassu
  0 siblings, 1 reply; 22+ messages in thread
From: Christian Brauner @ 2024-03-28 11:08 UTC (permalink / raw)
  To: Roberto Sassu
  Cc: Roberto Sassu, Al Viro, Steve French, LKML, linux-fsdevel, CIFS,
	Paulo Alcantara, Christian Brauner, Mimi Zohar, Paul Moore,
	linux-integrity, linux-security-module

On Thu, Mar 28, 2024 at 12:53:40PM +0200, Roberto Sassu wrote:
> On 3/26/2024 12:40 PM, Christian Brauner wrote:
> > > we can change the parameter of security_path_post_mknod() from
> > > dentry to inode?
> > 
> > If all current callers only operate on the inode then it seems the best
> > to only pass the inode. If there's some reason someone later needs a
> > dentry the hook can always be changed.
> 
> Ok, so the crash is likely caused by:
> 
> void security_path_post_mknod(struct mnt_idmap *idmap, struct dentry
> *dentry)
> {
>         if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> 
> I guess we can also simply check if there is an inode attached to the
> dentry, to minimize the changes. I can do both.
> 
> More technical question, do I need to do extra checks on the dentry before
> calling security_path_post_mknod()?

Why do you need the dentry? The two users I see are ima in [1] and evm in [2].
Both of them don't care about the dentry. They only care about the
inode. So why is that hook not just:

diff --git a/security/security.c b/security/security.c
index 7e118858b545..025689a7e912 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1799,11 +1799,11 @@ EXPORT_SYMBOL(security_path_mknod);
  *
  * Update inode security field after a file has been created.
  */
-void security_path_post_mknod(struct mnt_idmap *idmap, struct dentry *dentry)
+void security_inode_post_mknod(struct mnt_idmap *idmap, struct inode *inode)
 {
-       if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+       if (unlikely(IS_PRIVATE(inode)))
                return;
-       call_void_hook(path_post_mknod, idmap, dentry);
+       call_void_hook(path_post_mknod, idmap, inode);
 }

 /**

And one another thing I'd like to point out is that the security hook is
called "security_path_post_mknod()" while the evm and ima hooks are
called evm_post_path_mknod() and ima_post_path_mknod() respectively. In
other words:

git grep _path_post_mknod() doesn't show the implementers of that hook
which is rather unfortunate. It would be better if the pattern were:

<specific LSM>_$some_$ordered_$words()

[1]:
static void evm_post_path_mknod(struct mnt_idmap *idmap, struct dentry *dentry)
{
        struct inode *inode = d_backing_inode(dentry);
        struct evm_iint_cache *iint = evm_iint_inode(inode);

        if (!S_ISREG(inode->i_mode))
                return;

        if (iint)
                iint->flags |= EVM_NEW_FILE;
}

[2]:
static void ima_post_path_mknod(struct mnt_idmap *idmap, struct dentry *dentry)
{
        struct ima_iint_cache *iint;
        struct inode *inode = dentry->d_inode;
        int must_appraise;

        if (!ima_policy_flag || !S_ISREG(inode->i_mode))
                return;

        must_appraise = ima_must_appraise(idmap, inode, MAY_ACCESS,
                                          FILE_CHECK);
        if (!must_appraise)
                return;

        /* Nothing to do if we can't allocate memory */
        iint = ima_inode_get(inode);
        if (!iint)
                return;

        /* needed for re-opening empty files */
        iint->flags |= IMA_NEW_FILE;
}



> 
> Thanks
> 
> Roberto
> 
> > For bigger changes it's also worthwhile if the object that's passed down
> > into the hook-based LSM layer is as specific as possible. If someone
> > does a change that affects lifetime rules of mounts then any hook that
> > takes a struct path argument that's unused means going through each LSM
> > that implements the hook only to find out it's not actually used.
> > Similar for dentry vs inode imho.
> 

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: kernel crash in mknod
  2024-03-28 11:08             ` Christian Brauner
@ 2024-03-28 11:24               ` Roberto Sassu
  2024-03-28 12:07                 ` Christian Brauner
  2024-03-28 12:43                 ` Paul Moore
  0 siblings, 2 replies; 22+ messages in thread
From: Roberto Sassu @ 2024-03-28 11:24 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Roberto Sassu, Al Viro, Steve French, LKML, linux-fsdevel, CIFS,
	Paulo Alcantara, Christian Brauner, Mimi Zohar, Paul Moore,
	linux-integrity, linux-security-module

On 3/28/2024 12:08 PM, Christian Brauner wrote:
> On Thu, Mar 28, 2024 at 12:53:40PM +0200, Roberto Sassu wrote:
>> On 3/26/2024 12:40 PM, Christian Brauner wrote:
>>>> we can change the parameter of security_path_post_mknod() from
>>>> dentry to inode?
>>>
>>> If all current callers only operate on the inode then it seems the best
>>> to only pass the inode. If there's some reason someone later needs a
>>> dentry the hook can always be changed.
>>
>> Ok, so the crash is likely caused by:
>>
>> void security_path_post_mknod(struct mnt_idmap *idmap, struct dentry
>> *dentry)
>> {
>>          if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
>>
>> I guess we can also simply check if there is an inode attached to the
>> dentry, to minimize the changes. I can do both.
>>
>> More technical question, do I need to do extra checks on the dentry before
>> calling security_path_post_mknod()?
> 
> Why do you need the dentry? The two users I see are ima in [1] and evm in [2].
> Both of them don't care about the dentry. They only care about the
> inode. So why is that hook not just:

Sure, I can definitely do that. Seems an easier fix to do an extra check 
in security_path_post_mknod(), rather than changing the parameter 
everywhere.

Next time, when we introduce new LSM hooks we can try to introduce more 
specific parameters.

Also, consider that the pre hook security_path_mknod() has the dentry as 
parameter. For symmetry, we could keep it in the post hook.

What I was also asking is if I can still call d_backing_inode() on the 
dentry without extra checks, and avoiding the IS_PRIVATE() check if the 
former returns NULL.

> diff --git a/security/security.c b/security/security.c
> index 7e118858b545..025689a7e912 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -1799,11 +1799,11 @@ EXPORT_SYMBOL(security_path_mknod);
>    *
>    * Update inode security field after a file has been created.
>    */
> -void security_path_post_mknod(struct mnt_idmap *idmap, struct dentry *dentry)
> +void security_inode_post_mknod(struct mnt_idmap *idmap, struct inode *inode)
>   {
> -       if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> +       if (unlikely(IS_PRIVATE(inode)))
>                  return;
> -       call_void_hook(path_post_mknod, idmap, dentry);
> +       call_void_hook(path_post_mknod, idmap, inode);
>   }
> 
>   /**
> 
> And one another thing I'd like to point out is that the security hook is
> called "security_path_post_mknod()" while the evm and ima hooks are
> called evm_post_path_mknod() and ima_post_path_mknod() respectively. In
> other words:
> 
> git grep _path_post_mknod() doesn't show the implementers of that hook
> which is rather unfortunate. It would be better if the pattern were:
> 
> <specific LSM>_$some_$ordered_$words()

I know, yes. Didn't want to change just yet since people familiar with 
the IMA code know the current function name. I don't see any problem to 
rename the functions.

Thanks

Roberto

> [1]:
> static void evm_post_path_mknod(struct mnt_idmap *idmap, struct dentry *dentry)
> {
>          struct inode *inode = d_backing_inode(dentry);
>          struct evm_iint_cache *iint = evm_iint_inode(inode);
> 
>          if (!S_ISREG(inode->i_mode))
>                  return;
> 
>          if (iint)
>                  iint->flags |= EVM_NEW_FILE;
> }
> 
> [2]:
> static void ima_post_path_mknod(struct mnt_idmap *idmap, struct dentry *dentry)
> {
>          struct ima_iint_cache *iint;
>          struct inode *inode = dentry->d_inode;
>          int must_appraise;
> 
>          if (!ima_policy_flag || !S_ISREG(inode->i_mode))
>                  return;
> 
>          must_appraise = ima_must_appraise(idmap, inode, MAY_ACCESS,
>                                            FILE_CHECK);
>          if (!must_appraise)
>                  return;
> 
>          /* Nothing to do if we can't allocate memory */
>          iint = ima_inode_get(inode);
>          if (!iint)
>                  return;
> 
>          /* needed for re-opening empty files */
>          iint->flags |= IMA_NEW_FILE;
> }
> 
> 
> 
>>
>> Thanks
>>
>> Roberto
>>
>>> For bigger changes it's also worthwhile if the object that's passed down
>>> into the hook-based LSM layer is as specific as possible. If someone
>>> does a change that affects lifetime rules of mounts then any hook that
>>> takes a struct path argument that's unused means going through each LSM
>>> that implements the hook only to find out it's not actually used.
>>> Similar for dentry vs inode imho.
>>


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: kernel crash in mknod
  2024-03-28 11:24               ` Roberto Sassu
@ 2024-03-28 12:07                 ` Christian Brauner
  2024-03-28 13:03                   ` Paul Moore
  2024-03-28 12:43                 ` Paul Moore
  1 sibling, 1 reply; 22+ messages in thread
From: Christian Brauner @ 2024-03-28 12:07 UTC (permalink / raw)
  To: Roberto Sassu
  Cc: Roberto Sassu, Al Viro, Steve French, LKML, linux-fsdevel, CIFS,
	Paulo Alcantara, Christian Brauner, Mimi Zohar, Paul Moore,
	linux-integrity, linux-security-module

On Thu, Mar 28, 2024 at 01:24:25PM +0200, Roberto Sassu wrote:
> On 3/28/2024 12:08 PM, Christian Brauner wrote:
> > On Thu, Mar 28, 2024 at 12:53:40PM +0200, Roberto Sassu wrote:
> > > On 3/26/2024 12:40 PM, Christian Brauner wrote:
> > > > > we can change the parameter of security_path_post_mknod() from
> > > > > dentry to inode?
> > > > 
> > > > If all current callers only operate on the inode then it seems the best
> > > > to only pass the inode. If there's some reason someone later needs a
> > > > dentry the hook can always be changed.
> > > 
> > > Ok, so the crash is likely caused by:
> > > 
> > > void security_path_post_mknod(struct mnt_idmap *idmap, struct dentry
> > > *dentry)
> > > {
> > >          if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
> > > 
> > > I guess we can also simply check if there is an inode attached to the
> > > dentry, to minimize the changes. I can do both.
> > > 
> > > More technical question, do I need to do extra checks on the dentry before
> > > calling security_path_post_mknod()?
> > 
> > Why do you need the dentry? The two users I see are ima in [1] and evm in [2].
> > Both of them don't care about the dentry. They only care about the
> > inode. So why is that hook not just:
> 
> Sure, I can definitely do that. Seems an easier fix to do an extra check in
> security_path_post_mknod(), rather than changing the parameter everywhere.

You only have two callers and the generic implementation.

> 
> Next time, when we introduce new LSM hooks we can try to introduce more
> specific parameters.
> 
> Also, consider that the pre hook security_path_mknod() has the dentry as
> parameter. For symmetry, we could keep it in the post hook.

I think that's not that important.

> 
> What I was also asking is if I can still call d_backing_inode() on the
> dentry without extra checks, and avoiding the IS_PRIVATE() check if the
> former returns NULL.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: kernel crash in mknod
  2024-03-28 11:24               ` Roberto Sassu
  2024-03-28 12:07                 ` Christian Brauner
@ 2024-03-28 12:43                 ` Paul Moore
  1 sibling, 0 replies; 22+ messages in thread
From: Paul Moore @ 2024-03-28 12:43 UTC (permalink / raw)
  To: Roberto Sassu
  Cc: Christian Brauner, Roberto Sassu, Al Viro, Steve French, LKML,
	linux-fsdevel, CIFS, Paulo Alcantara, Christian Brauner,
	Mimi Zohar, linux-integrity, linux-security-module

On Thu, Mar 28, 2024 at 7:24 AM Roberto Sassu
<roberto.sassu@huaweicloud.com> wrote:
> On 3/28/2024 12:08 PM, Christian Brauner wrote:

...

> > And one another thing I'd like to point out is that the security hook is
> > called "security_path_post_mknod()" while the evm and ima hooks are
> > called evm_post_path_mknod() and ima_post_path_mknod() respectively. In
> > other words:
> >
> > git grep _path_post_mknod() doesn't show the implementers of that hook
> > which is rather unfortunate. It would be better if the pattern were:
> >
> > <specific LSM>_$some_$ordered_$words()
>
> I know, yes. Didn't want to change just yet since people familiar with
> the IMA code know the current function name. I don't see any problem to
> rename the functions.

I'm sure this is what you are planning Roberto, but just so we are all
clear on this, please do the simple bugfix to resolve the mknod
problem and then do the parameter change and the name bikeshedding in
a separate patch.

-- 
paul-moore.com

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: kernel crash in mknod
  2024-03-28 12:07                 ` Christian Brauner
@ 2024-03-28 13:03                   ` Paul Moore
  0 siblings, 0 replies; 22+ messages in thread
From: Paul Moore @ 2024-03-28 13:03 UTC (permalink / raw)
  To: Roberto Sassu, Christian Brauner
  Cc: Roberto Sassu, Al Viro, Steve French, LKML, linux-fsdevel, CIFS,
	Paulo Alcantara, Christian Brauner, Mimi Zohar, linux-integrity,
	linux-security-module

On Thu, Mar 28, 2024 at 8:07 AM Christian Brauner <brauner@kernel.org> wrote:
> On Thu, Mar 28, 2024 at 01:24:25PM +0200, Roberto Sassu wrote:
> > Also, consider that the pre hook security_path_mknod() has the dentry as
> > parameter. For symmetry, we could keep it in the post hook.
>
> I think that's not that important.

It is important to me.  If you change security_path_post_mknod() to
take an inode, please also change security_path_mknod() to take an
inode ... actually, looking quickly at the code it looks like at least
AppArmor and TOMOYO make use of the dentry and not just the associated
inode.  I didn't dive deeply into either so perhaps they could be
modified to use an inode instead, but that is a decision I would leave
up to John and Tetsuo.  While Landlock does make use of the hook, it
doesn't look like it cares about anything in the dentry.

With that in mind, unless Christian has a strong argument as to why
security_path_post_mknod() must change its parameter from a dentry to
an inode, I would very much prefer to have both hooks continue to take
a dentry, unless we all decide they can be safely changed to use an
inode as a parameter.  As the previous IMA/EVM hook took a dentry for
years, and Christian originally reviewed/OK'd the LSM hook, I'm
guessing there is not any significant harm in continuing to pass a
dentry, but if that isn't the case please say so ...

Of course this doesn't change anything with respect to the necessary
bugfix and/or the hook name/bikeshedding effort; no objections from me
on either.

-- 
paul-moore.com

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2024-03-28 13:03 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-24  5:00 kernel crash in mknod Steve French
2024-03-24  5:46 ` Al Viro
2024-03-24  6:31   ` Al Viro
2024-03-24 16:50   ` Roberto Sassu
2024-03-24 21:02     ` Al Viro
2024-03-25 16:06     ` Christian Brauner
2024-03-25 17:18       ` Roberto Sassu
2024-03-26 11:40         ` Christian Brauner
2024-03-26 12:53           ` Paul Moore
2024-03-28 10:53           ` Roberto Sassu
2024-03-28 11:08             ` Christian Brauner
2024-03-28 11:24               ` Roberto Sassu
2024-03-28 12:07                 ` Christian Brauner
2024-03-28 13:03                   ` Paul Moore
2024-03-28 12:43                 ` Paul Moore
2024-03-25 17:21       ` Paul Moore
     [not found]       ` <CAH2r5muL4NEwLxq_qnPOCTHunLB_vmDA-1jJ152POwBv+aTcXg@mail.gmail.com>
2024-03-25 19:54         ` Al Viro
2024-03-25 20:46           ` Al Viro
2024-03-25 20:47           ` Paulo Alcantara
2024-03-25 21:13             ` Al Viro
2024-03-25 21:31               ` Paulo Alcantara
2024-03-25 17:05     ` Paul Moore

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.