3

I frequently run a script that creates three files in /tmp and then moves them to the destination directory. I was puzzled by the error messages:

mv: ./20170608-l.gpx: set owner/group (was: 503/0): Operation not permitted
mv: ./20170608-u.gpx: set owner/group (was: 503/0): Operation not permitted
mv: ./20170608.csv: set owner/group (was: 503/0): Operation not permitted

The script doesn't use sudo, so the group wheel (zero) seemed odd. Checking /tmp (/private/tmp) shows the sticky bit is on it. But forcing the group to be wheel (which I expect that to happen) is not what Wikipedia (quoting a Leopard man page) says it will do. And preventing me from changing the group on the copy is neither. The copy ends up with the same owner—me—and my group—staff—so it actually did what it said was not permitted.

I can see a rationale for what the man page says, but why does the error message say that something different was not allowed when it actually did exactly that? And why are files in /tmp created with group wheel when that is not what the sticky bit is for?

/tmp is root/wheel as expected,

WGroleau@MBP ~ % ls -latde@ /private/tmp
drwxrwxrwt  7 root  wheel  224 Dec 21 09:58 /private/tmp

but the doc mentioned says that sticky bit prevents deletion by someone else but the owner. Since I was the owner, that doesn't matter. But it doesn't say what I thought it meant, which was to override the creator's group. However, the latter is what did happen. And then the error message falsely states that it was not able to change the group to mine. Not sure whether changing the group is required when the destination does not have a sticky bit:

WGroleau@MBP ~ % ls -late@d /Volumes/Sidecar/Sort_By_Date/2017年/06月/08日
drwxrwxr-x  16 WGroleau  staff  512 Dec 20 23:35 /Volumes/Sidecar/Sort_By_Date/2017年/06月/08日
8
  • 2
    I can't reproduce this here, moving a file from /tmp to my own directory doesn't throw an error (and leaves ownership at user:wheel), copying also works (and changes group ownership). Do you mv or cp? Which permissions are set on the target directory, which on /private/tmp (please run ls -ld on both)?
    – nohillside
    Commented Dec 21, 2022 at 9:48
  • The script has mv but the destination is on an external disk, therefore (I assume) it actually does a copy-then-remove. But the destination has the correct owner/group/mode and the source is deleted in spite of the message implying otherwise.
    – WGroleau
    Commented Dec 21, 2022 at 18:23
  • Ah, that's an important addition. How is the external disk formatted?
    – nohillside
    Commented Dec 21, 2022 at 18:24
  • Both the internal SSD and the external spinner are APFS. (Which should not make mv behave differently in any visible way.)
    – WGroleau
    Commented Dec 21, 2022 at 18:27
  • Ah, interesting. Suspected FAT32, but I can reproduce it for both FAT32 and APFS.
    – nohillside
    Commented Dec 21, 2022 at 18:30

2 Answers 2

4

The source code for mv is available on Github, the part relating to the error is in line 448.

oldmode = sbp->st_mode & ALLPERMS;
if (fchown(to_fd, sbp->st_uid, sbp->st_gid)) {
    warn("%s: set owner/group (was: %lu/%lu)", to, (u_long)sbp->st_uid, (u_long)sbp->st_gid);
    if (oldmode & (S_ISUID | S_ISGID)) {
        warnx("%s: owner/group changed; clearing suid/sgid (mode was 0%03o)", to, oldmode);
        sbp->st_mode &= ~(S_ISUID | S_ISGID);
    }
}

What actually happens within mv is the following:

  • As this is a regular file getting moved to an another filesystem, the command can't use the standard rename() system call but uses an internal function to create a new file on the target filesystem, copy the content over and then delete the source file
  • Initially the target file is created with the default group of the user (usually staff)
  • After the copy is done, the command tries to apply the owner and group of the source file to the newly created target (the fchown() call in the second line of the code snippet above
  • Files in /tmp belong to group wheel but normal users are not part of that group, so fchown() fails, leading to the warning message.

This also means that sudo mv /tmp/foo /Volumes/External/ will succeed without a warning:

$ touch /tmp/foo
$ mv /tmp/foo /Volumes/EXT
mv: /Volumes/EXT/foo: set owner/group (was: 502/0): Operation not permitted
$ touch /tmp/foo
$ sudo mv /tmp/foo /Volumes/EXT
$
3
  • The third bullet explains it. I still don't get why the man page for sticky(7) says nothing about overriding group, which is what happened in this case, and what it has always done for me.
    – WGroleau
    Commented Dec 21, 2022 at 23:38
  • @WGroleau the sticky bit on /tmp works as intended, it’s purely the mv which has a problem.
    – nohillside
    Commented Dec 21, 2022 at 23:47
  • I can see the 'mv' issue, but forcing the group to be wheel when the file is created is not what the man page says the sticky bit is for. Although that is what I've always used it for.
    – WGroleau
    Commented Dec 22, 2022 at 0:55
3

Your question comes from a misunderstanding of why the files have wheel as group - as it simply doesn't have anything at all to do with the sticky bit.

The sticky bit works as intended - and does what it has always done. There's no special handling for the /tmp folder in that regards.

In general, a user that has write and execute permissions for a directory is allowed to rename and delete files in that directory. As you see in your paste, all others have write and execute permissions on the /tmp directory. This creates the problem that any user can delete other user's temporary files. That is not desirable.

The sticky bit solves this by declaring to the system that you do not want the usual semantics of directory permissions. Instead only the owner of the file, the owner of the /tmp directory or the root user can rename and delete files in /tmp.

So that was the sticky bit - nothing in that explanation said anything about the group wheel.

That comes from a basic fact about file system permissions on Unix-like systems, such as for example macOS. It is so that when you create a file on these systems, the group of the new file is by default the group of the folder the file is created in. As the /tmp folder has group wheel, new files created in the /tmp folder will by default have group wheel.

When you later try to move files from /tmp to other file systems, the mv program will try to make the destination file have the same owner and group as the original file. This fails because you cannot set the group of the new file to wheel - instead the file ends up having the default group - namely the group of the folder where the file is created.

7
  • "nothing in that explanation said anything about the group wheel." Exactly my point. What the description says makes sense, but in my thirty years experience in software, I have often used a sticky bit to override the owner or group of an existing file, not to override the creator's id/group for creating a file. And this is the first time I've seen a new file inheriting its directory's group instead of its creator's group (except when created by a script with a sticky bit)
    – WGroleau
    Commented Dec 22, 2022 at 19:40
  • You're misunderstanding this. I'm explaining to you how the sticky bit works - it has nothing at all to do with what you're seeing with the wheel group. I'm not repeating a description from somewhere else and noting that their description somehow left out this important part of how the sticky bit works. The sticky bit is completely irrelevant here.
    – jksoegaard
    Commented Dec 22, 2022 at 21:03
  • It might be that it is the first time you have seen a new file inheriting the group of it's directory - but that's how it works, and how it has worked for decades. This is simply how file creation works on macOS and other Unixoid systems. New files do NOT inherit the creator's group. Scripts with a sticky bit means something entirely different than directories with sticky bits - it means that the script runs as that user. Again, that doesn't have anything to do with the group given to files that are created by that script. It only says something about what it can change the group to afterwards
    – jksoegaard
    Commented Dec 22, 2022 at 21:06
  • That makes sense. I wonder if it relates to me occasionally finding things in my home directory that aren't owned by me. Is root (sudo) exempt from that inheriting rule? (when you said "explanation," I thought you meant the man page)
    – WGroleau
    Commented Dec 22, 2022 at 21:22
  • No, the root user is not exempt from that rule. It works that way for everyone. However, the root user is able to change the group of the file after creation to anything he likes.
    – jksoegaard
    Commented Dec 23, 2022 at 9:58

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .