Index | Thread | Search

From:
Martijn van Duren <openbsd+tech@list.imperialat.at>
Subject:
Re: Message when moving file to ext2
To:
Walter Alejandro Iglesias <wai@roquesor.com>, tech@openbsd.org
Date:
Thu, 23 Oct 2025 02:14:41 +0200

Download raw body.

Thread
On Wed, 2025-10-22 at 21:35 +0200, Walter Alejandro Iglesias wrote:
> Hello list,
> 
> Is the message below expected when moving a file to an ext2 file system?
> 
>   $ doas mount -t ext2fs /dev/sd1i /mnt
>   $ mv file /mnt
>   mv: /mnt/file: set flags: Operation not permitted
> 
Moving to tech@

I ran into this issue some time ago with install(1). Back then I fixed
it by making sure that install(1) doesn't call chflags(2) when the flags
are identical.

The culprit for this warning is the following diff[0], which now always
returns EPERM when a user tries to change flags (which we clearly aren't
trying to do). Since I can't tell which other tools might bite us I
think it might be wise to implement the logic I put into install(1) into
the ext2fs driver.

The diff below works on my machine(tm). Could you give it a spin?

martijn@

ps. ext2 has a few more flags than our tools support[1]. But we could
add nodump to the mapping, if only for a bit more complete insight.
pps. Maybe it's a good idea to return EINVAL for UF_IMMUTABLE,
UF_APPEND, and SF_ARCHIVED. That way it will be clear for the
admin that certain flags aren't supported and won't be dropped
silently. 

[0] https://marc.info/?l=openbsd-tech&m=174499208717194&w=2
[1] https://wiki.osdev.org/Ext2#Inode_Flags

diff /usr/src
path + /usr/src
commit - 243c12c31b603d599722a28305b1c1bab6ea9d19
blob - c0ffdeb9166c32d67d308129cd4c7c5b535cc620
file + sys/ufs/ext2fs/ext2fs_vnops.c
--- sys/ufs/ext2fs/ext2fs_vnops.c
+++ sys/ufs/ext2fs/ext2fs_vnops.c
@@ -210,6 +210,7 @@ ext2fs_setattr(void *v)
 	struct vnode *vp = ap->a_vp;
 	struct inode *ip = VTOI(vp);
 	struct ucred *cred = ap->a_cred;
+	u_long e2flags;
 	int error;
 
 	/*
@@ -227,16 +228,17 @@ ext2fs_setattr(void *v)
 		if (cred->cr_uid != ip->i_e2fs_uid &&
 			(error = suser_ucred(cred)))
 			return (error);
+		e2flags = (vap->va_flags & SF_APPEND) ? EXT2_APPEND : 0 |
+		    (vap->va_flags & SF_IMMUTABLE) ? EXT2_IMMUTABLE: 0;
 		if (cred->cr_uid == 0) {
 			if ((ip->i_e2fs_flags &
 			    (EXT2_APPEND | EXT2_IMMUTABLE)) && securelevel > 0)
 				return (EPERM);
 			ip->i_e2fs_flags &= ~(EXT2_APPEND | EXT2_IMMUTABLE);
-			ip->i_e2fs_flags |=
-			    (vap->va_flags & SF_APPEND) ? EXT2_APPEND : 0 |
-			    (vap->va_flags & SF_IMMUTABLE) ? EXT2_IMMUTABLE: 0;
+			ip->i_e2fs_flags |= e2flags;
 		} else {
-			return (EPERM);
+			if (e2flags != ip->i_e2fs_flags)
+				return (EPERM);
 		}
 		ip->i_flag |= IN_CHANGE;
 		if (vap->va_flags & (IMMUTABLE | APPEND))