[v2,2/3] fs: ubifs: update i_version on inode changes

Message ID 20170411095055.26328-3-o.rempel@pengutronix.de
State Deferred, archived
Delegated to: Richard Weinberger
Headers show

Commit Message

Oleksij Rempel April 11, 2017, 9:50 a.m.
increment i_version to notify security/IMA about changes
made in inode.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 fs/ubifs/file.c | 9 +++++++++
 1 file changed, 9 insertions(+)

Comments

Christoph Hellwig April 11, 2017, 4:05 p.m. | #1
On Tue, Apr 11, 2017 at 11:50:54AM +0200, Oleksij Rempel wrote:
> increment i_version to notify security/IMA about changes
> made in inode.
> 
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>

And how is this stored on disk?
Richard Weinberger April 11, 2017, 9:13 p.m. | #2
Am 11.04.2017 um 18:05 schrieb Christoph Hellwig:
> On Tue, Apr 11, 2017 at 11:50:54AM +0200, Oleksij Rempel wrote:
>> increment i_version to notify security/IMA about changes
>> made in inode.
>>
>> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> 
> And how is this stored on disk?
> 

Hehe, I was about to ask the same question. :-)

Thanks,
//richard
Oleksij Rempel April 12, 2017, 6:05 a.m. | #3
On Tue, Apr 11, 2017 at 11:13:24PM +0200, Richard Weinberger wrote:
> Am 11.04.2017 um 18:05 schrieb Christoph Hellwig:
> > On Tue, Apr 11, 2017 at 11:50:54AM +0200, Oleksij Rempel wrote:
> >> increment i_version to notify security/IMA about changes
> >> made in inode.
> >>
> >> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> > 
> > And how is this stored on disk?
> > 
> 
> Hehe, I was about to ask the same question. :-)

No. it is not stored to fs.
Heh, the same question i asked my self. On linux-ima-user i found
this post (2009-07-23):
https://sourceforge.net/p/linux-ima/mailman/message/23152923/
---
When an inode entry is removed from dcache, the corresponding iint entry
is removed from the radix tree. Unmounting an fs will cause the inodes,
and by extension iint's, to be freed.  When the fs is remounted, any
file accessed will result in allocating a new iint structure with the
i_version set to 0.
---

The code seems to confirm it. So i assumed that IMA don't care if
i_version is stored to disk or not. And i_version is the only way
to notify IMA about inode changes.
Since IMA documentation explecitley set i_version as reqieremt, so this
option was provided as well.
Christoph Hellwig April 12, 2017, 6:08 a.m. | #4
On Wed, Apr 12, 2017 at 08:05:34AM +0200, Oleksij Rempel wrote:
> The code seems to confirm it. So i assumed that IMA don't care if
> i_version is stored to disk or not. And i_version is the only way
> to notify IMA about inode changes.
> Since IMA documentation explecitley set i_version as reqieremt, so this
> option was provided as well.

Maybe IMA doesn't care, but if you set MS_I_VERSION the fs does give
a guarantee.  Sp NAK on this patch as-is.
Oleksij Rempel April 12, 2017, 7:04 a.m. | #5
On Tue, Apr 11, 2017 at 11:08:47PM -0700, Christoph Hellwig wrote:
> On Wed, Apr 12, 2017 at 08:05:34AM +0200, Oleksij Rempel wrote:
> > The code seems to confirm it. So i assumed that IMA don't care if
> > i_version is stored to disk or not. And i_version is the only way
> > to notify IMA about inode changes.
> > Since IMA documentation explecitley set i_version as reqieremt, so this
> > option was provided as well.
> 
> Maybe IMA doesn't care, but if you set MS_I_VERSION the fs does give
> a guarantee.  Sp NAK on this patch as-is.

Ok, it was an expekted NACK :)
Suddenly right now i don't have good ide to solve it. IMA just won't to
know if some runtime changes was made to FS. Currently i can image
fallowing variants:
- rework IMA
- add MS_I_TEMP_VERSION and keep i_version using for it.
- add new variable for external use only. For example: ima_rt_i_version,
  or some thing like this.

Other ideas?
Richard Weinberger April 24, 2017, 3:44 p.m. | #6
Oleksij,

Am 12.04.2017 um 09:04 schrieb Oleksij Rempel:
> On Tue, Apr 11, 2017 at 11:08:47PM -0700, Christoph Hellwig wrote:
>> On Wed, Apr 12, 2017 at 08:05:34AM +0200, Oleksij Rempel wrote:
>>> The code seems to confirm it. So i assumed that IMA don't care if
>>> i_version is stored to disk or not. And i_version is the only way
>>> to notify IMA about inode changes.
>>> Since IMA documentation explecitley set i_version as reqieremt, so this
>>> option was provided as well.
>>
>> Maybe IMA doesn't care, but if you set MS_I_VERSION the fs does give
>> a guarantee.  Sp NAK on this patch as-is.
> 
> Ok, it was an expekted NACK :)
> Suddenly right now i don't have good ide to solve it. IMA just won't to
> know if some runtime changes was made to FS. Currently i can image
> fallowing variants:
> - rework IMA

I assumed that you checked that option already. I IMA *really* needs i_version,
we can think of an solution. Adding new filesystem features should be done with
care.

> - add MS_I_TEMP_VERSION and keep i_version using for it.

You mean a non-persistent i_version like fat and exofs use internally?

> - add new variable for external use only. For example: ima_rt_i_version,
>   or some thing like this.

hch will hate this for very good reasons. :-)

> Other ideas?

What about making i_version persistent?
We still have some empty fields in UBIFS' inode data structure.
But first we have to be very sure that we need it.

Artem, do you remember why UBIFS does not store i_version?

Thanks,
//richard

Patch

diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index d9ae86f96df7..29213724259b 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1104,6 +1104,8 @@  static void do_attr_changes(struct inode *inode, const struct iattr *attr)
 			mode &= ~S_ISGID;
 		inode->i_mode = mode;
 	}
+	if (IS_I_VERSION(inode))
+		inode_inc_iversion(inode);
 }
 
 /**
@@ -1401,6 +1403,9 @@  int ubifs_update_time(struct inode *inode, struct timespec *time,
 	if (!(inode->i_sb->s_flags & MS_LAZYTIME))
 		iflags |= I_DIRTY_SYNC;
 
+	if (IS_I_VERSION(inode))
+		inode_inc_iversion(inode);
+
 	release = ui->dirty;
 	__mark_inode_dirty(inode, iflags);
 	mutex_unlock(&ui->ui_mutex);
@@ -1435,6 +1440,8 @@  static int update_mctime(struct inode *inode)
 
 		mutex_lock(&ui->ui_mutex);
 		inode->i_mtime = inode->i_ctime = ubifs_current_time(inode);
+		if (IS_I_VERSION(inode))
+			inode_inc_iversion(inode);
 		release = ui->dirty;
 		mark_inode_dirty_sync(inode);
 		mutex_unlock(&ui->ui_mutex);
@@ -1580,6 +1587,8 @@  static int ubifs_vm_page_mkwrite(struct vm_fault *vmf)
 
 		mutex_lock(&ui->ui_mutex);
 		inode->i_mtime = inode->i_ctime = ubifs_current_time(inode);
+		if (IS_I_VERSION(inode))
+			inode_inc_iversion(inode);
 		release = ui->dirty;
 		mark_inode_dirty_sync(inode);
 		mutex_unlock(&ui->ui_mutex);