Hacker News new | past | comments | ask | show | jobs | submit login
Casually removing root files (ervinb.github.io)
128 points by ervinb on Aug 16, 2017 | hide | past | favorite | 55 comments



> The only requirement is to have write permissions on the parent directory (and the execute flag on the parent directory).

> The $HOME directory naturally fulfills both of these requirements from the user’s perspective.

Note that there's nothing special about the user's home directory here, it just happens to normally have u+wx. It's entirely possible to have the user's home not owned by themselves; you might want to do this for example if you have a restricted user who you don't want messing around with their dotfiles.


Isn't this just a roundabout way of saying that you can remove files from a directory you have write access to? What's the relevance here?


The point seems to be that this isn't expected behavior in most people's minds, and that if someone truly wants to allow users to write to a directory, but not allow them to delete a file, that file must be flagged immutable. Just a quirky edge cases that people might not know about.


It is expected behaviour if your mental model is accurate enough.

My mental model is that a directory is just a special file that links to other files.

Adding or deleting a file to a directory is just a case of writing to the "special file" to add or remove links to other files.


The statement 'it is the expected behavior if your mental model is accurate enough' is a tautology.


saying that tautologies are tautologies is tautological.


it only tautological to say "X is a tautology" to those who had recognized X as being a tautology.


The correct answer to "many people find this confusing" is never "I don't, so it's fine."


But there's a difference between confusion that arises because something is complex or inconsistent and confusion that arises because people have the wrong mental model.

"I assume that SQL tables are basically just fancy CSV files. Therefore strong invariants are obviously confusing."


If most serious users have the wrong mental model about something, then either there's a serious documentation/training failure, or the correct model is non-obvious and counterintuitive (or both). Blaming the users for their ignorance is not productive in either case.


But if the file you are removing is the only reference (i.e. hard link) to that inode, you're not just modifying the directory's contents; you're also removing data from the filesystem as a whole.


Note that something else also happens to the inode when it's not the only reference: removing a file changes the "nlink" counter on the inode.


Right. You are only affecting that directory listing.

Any other hardlinks in any other directories are completely unaffected.


That comment comes across as very arrogant. Of course if you're familiar enough with the system then you'll have no need to read this, and you can go off and seek gratification installing Gentoo and telling everyone about it.

But some people don't know, and benefit from learning it. So chill.


How do you fit immutable files into that mental model?


I did not know about immutable, but I have noticed that c9.io uses another way to avoid modification of a file present in a directory that I own. It makes it a read only mount point: /dev/mapper/volg1-lvdata on /home/ubuntu/.ssh/authorized_keys type ext4 (ro,relatime,data=ordered)


Well, although that is obvious, I did learn something new: that on Linux, you can prevent linking, unlinking and renaming using chattr.


I thought the reason the file could be written or deleted by the user was that it had no permissions set... wouldn't this not work if root chmodded little-rock to 600?


No. This would have worked the same if it were chmod 600.

The point of chmod 000 was to say that clearly nobody has any any permissions to do anything directly on the file; that the permissions on the file must have nothing to do with it.


Okay, so deleting or renaming a file is considered a change of the directory information. Therefore, a user's ability to do that to a file is dependent upon the directory's permissions. And one can avoid that by setting the immutable bit. Got it... I think i was distracted by the parable.


Yes and every OS these days likes to squire away perms in random utils which you have to google for, I don’t see why the normal interface can’t just be updated if needed. Really annoying.


My use case for `chattr +i`: an rsync backup, on a cronjob, into an external drive mounted at a given point. Make the mountpoint directory `+i` so that the root-run rsync doesn't blindly fill up your root filesystem with the backup target, if it gets run while the external drive isn't mounted.


Thanks for this tip! I've been achieving this by pointing a symlink at a subdirectory that only exists when the external drive is mounted, and having my backups target that symlink. But this seems cleaner.


Me too. Not sure why using an immutable mountpoint is better than a possibly broken symlink, both result in a write failure. I like the symlink, because it's visually obvious when it's broken in the shell, and I can keep my real mounts under /mnt or /pool etc while also putting the target (symlink) in /home/user.


Also useful: "mountpoint" can tell you if a path is mounted.

https://linux.die.net/man/1/mountpoint

E.g.

  mountpoint -q /mnt/backup || exit 1


What if it gets unmounted right after the mountpoint call :)


What if it gets mounted just before you run chattr +i :)

I agree setting the flag is the superior option.


You miss the point of making a directory immutable which doubles as a mountpoint.

Mounting something just creates a new filsystem namespace over a path. It doesn't touch the existing directory.

So you can safely leave the directory in question immutable, you never remove the flag, and it will only prevent writes to the directory when it is not overlaid by a mount.


That's pretty cute. `chattr +i' can be pretty handy for preventing misbehaving tools which must run as root from mangling your precious files. Also for messing with people on multi-user boxes :)

As a tiny issue, in the 3rd snippet, '/home/user/shoe/little-rock' should be left-shoe, no?


It can also be helpful if you have a mountpoint that normally points at a remote machine (backup machine, etc), but that remote machine is unavailable for some reason. It keeps your backups from going into the mountpoint itself instead of the intended destination.


> As a tiny issue, in the 3rd snippet, '/home/user/shoe/little-rock' should be left-shoe, no?

Yes, that part probably doubled the time it took me to read the first part of the post, because I had to double-check everything.


Thanks guys for pointing that out! I just updated the text.


The 'any permissions' link is broken, too.


Fixed. Thanks a lot!


>Listing a directory’s contents is controlled by the execute flag.

Listing is controlled by r--. Access to content items is controlled by --x.


Indeed.

--x in the context of directories is typically called "search" permission rather than execute.


This is a sort of fundamental thing about POSIX: file data is attached to a pretty bare data-structure (the thing a Linux inode/BSD vnode points to), while most of the metadata is instead held in the individual dirents referencing that inode/vnode. creat(2), rename(2), and unlink(2) don't have to touch the file they're affecting; they just modify the contents of a directory, with [iv]nodes being allocated or destroyed through reference-counting as a side-effect.

To put that another way: when you delete a file in POSIX, you're not writing to the file, you're just writing to the directory. (Think of a directory as just a file containing a stream of dirent data—if you have write permission on it, you can modify the dirents.) After you remove a dirent, the kernel then goes and cleans up the file if its link count has become zero—and, obviously, the kernel has permission to do that.


This reminds me of the time (albeit my memory is hazy) of an issue of having to set `chattr -i` on .ssh files because even though I had the right chmod permissions SSH still would not read it. It was quite painful to figure out and I can't recall if I googled it or read it in the man pages.

I believe it was because I had done something funny with the home directory and the user didn't fully own it (I believe it was a home media server).

I guess apparently some SSH versions expect `chattr -i` or I guess the parent directory to be owned completely by the user (I have been meaning to look into this some day). Maybe it wasn't -i .. maybe it was +i?


The .ssh directory and its contents must be non-writable by anyone but the user. That means the group must not have write access, even if the user is the only person in the group. Commonly, there is a group for each user with the same name, so the "fred" user will have a "fred" group with only the "fred" user being a member. This group mustn't have write access. Also, private keys must be unreadable by anyone but the user. You don't need to make the files immutable.


It wasn't chattr.

It was this problem with SELinux: https://stackoverflow.com/a/21636460/318174

    restorecon -R -v /root/.ssh
I was confused because I have used chattr with ssh files before just for added security. My memory was also hazy because I don't know much about SELinux. Hopefully I didn't misguide anyone.


chattr appears to be a Linuxism, but TFA doesn't mention that.



AFIACS, chattr(1) can be compiled on BSDs too; and then it uses the chflags(2) syscall.


> If the Rock Tamer, really didn’t want anyone to mess around with his rocks, he would’ve done:

> # chattr +i /home/user/left-shoe/little-rock

Or more traditionally, chmod +t /home/user/left-shoe

though that would affect other files.


I was using chattr +i as a quick workaround to the fact that Ubuntu overwrites Xorg.conf every time you restart it, which overwrote my nvidia GPU overclock settings. Setting +i made it immutable.


You should be using /etc/X11/xorg.conf.d/*.conf for that.


No, this path will not work. If anything it should be /usr/share/X11/xorg.conf.d


If you're using Slackware, or another sane distribution, /etc/X11/xorg.conf.d/ is where you put user-specific X configuration. Making the config immutable would prevent overwrite.

Making local edits in any part of /usr/ is extremely frowned upon.


Apologies. I haven't been using Ubuntu in a while and did not know you had to modify stuff under /usr there. (Eww!)


This is only true for some filesystems. ext4 notably doesn't acknowledge -i attribute


Not true. Immutable works just fine on ext4.

https://pastebin.com/beuimxR8


Indeed. The list of all supported attributes is in the manual page:

http://man7.org/linux/man-pages/man5/ext4.5.html#FILE_ATTRIB...


Ah, you're right, I mis-remembered: """ The `c', 's', and `u' attributes are not honored by the ext2, ext3, and ext4 filesystems as implemented in the current mainline Linux kernels. """


If one must install grub to a partition (e.g. on a first-generation Mac Pro), one is advised on the ArchLinux Wiki to use chattr:

Warning: GRUB strongly discourages installation to a partition boot sector or a partitionless disk as GRUB Legacy or Syslinux does. This setup is prone to breakage, especially during updates, and is not supported by the Arch developers.

# chattr -i /boot/grub/i386-pc/core.img

# grub-install --target=i386-pc --debug --force /dev/sdaX

# chattr +i /boot/grub/i386-pc/core.img

in case of partition or a partitionless disk is that GRUB relies on embedded blocklists in the partition bootsector to locate the /boot/grub/i386-pc/core.img file and the prefix directory /boot/grub. The sector locations of core.img may change whenever the file system in the partition is being altered (files copied, deleted etc.).

The workaround for this is to set the immutable flag on /boot/grub/i386-pc/core.img (using chattr command as mentioned above) so that the sector locations of the core.img file in the disk is not altered. The immutable flag on /boot/grub/i386-pc/core.img needs to be set only if GRUB is installed to a partition boot sector or a partitionless disk, not in case of installation to MBR or simple generation of core.img without embedding any bootsector (mentioned above).

https://wiki.archlinux.org/index.php/GRUB/Tips_and_tricks


This is a very useful trick, and allows for the design of ridiculously simple bootloaders. If you +i vmlinux, IIRC you can fit a loader for it into 448 bytes.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: