
Casually removing root files - ervinb
https://ervinb.github.io/2017/08/16/casually-removing-root-files/
======
wolfgang42
_> 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.

------
JimDabell
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?

~~~
etskinner
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.

~~~
jstanley
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.

~~~
yberreby
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.

~~~
glandium
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.

------
alethiophile
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.

~~~
Renevith
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.

~~~
jakeogh
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.

------
shabble
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?

~~~
dEnigma
> _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.

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

~~~
code_duck
The 'any permissions' link is broken, too.

~~~
ervinb
Fixed. Thanks a lot!

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

 _Listing_ is controlled by r--. _Access to content items_ is controlled by
--x.

~~~
emmelaich
Indeed.

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

------
derefr
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.

------
agentgt
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?

~~~
mnw21cam
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.

~~~
agentgt
It wasn't chattr.

It was this problem with SELinux:
[https://stackoverflow.com/a/21636460/318174](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.

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

~~~
quazeekotl
BSDs also have a command that does the same thing, but its called chflags

[https://man.openbsd.org/chflags.1](https://man.openbsd.org/chflags.1)

[https://www.freebsd.org/cgi/man.cgi?query=chflags](https://www.freebsd.org/cgi/man.cgi?query=chflags)

[http://netbsd.gw.com/cgi-bin/man-cgi?chflags](http://netbsd.gw.com/cgi-
bin/man-cgi?chflags)

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

------
emmelaich
> _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.

------
lossolo
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.

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

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

~~~
peterwwillis
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.

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

~~~
teilo
Not true. Immutable works just fine on ext4.

[https://pastebin.com/beuimxR8](https://pastebin.com/beuimxR8)

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

[http://man7.org/linux/man-
pages/man5/ext4.5.html#FILE_ATTRIB...](http://man7.org/linux/man-
pages/man5/ext4.5.html#FILE_ATTRIBUTES)

~~~
reptation
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. """

------
aleden
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](https://wiki.archlinux.org/index.php/GRUB/Tips_and_tricks)

~~~
exikyut
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.

