0

System: x86_64 Linux 5.13.19-2-MANJARO.

I have a weird directory in '~/.local/share/Trash/expunged' which contains a few directories owned by the user nobody. I tried to execute the following command as root:

rm -rf pathToWeirdDirectory

which yields in the following error message

rm: cannot remove 'pathToWeirdDirectory': Value too large for defined data type

After changing the directory ownership using

chown me:me pathToWeirdDirectory

I finally succeeded to remove the directory. There are some more directories of this type with several subdirectories containing multiple files. I have tried to execute the following command:

chown -R me:me pathToSecondWeirdDirectory

which yields to the following error message:

chown: cannot read directory 'pathToSeconWeirdDirectory/subdirectory1/subdirectory2': Permission denied

As far as I was concerned the '-R' flag changes ownerships recursively for the given directory, thus I created the following test case:

directory/
    file
    subdirectory/
    file2

owned by user me. I successfully changed its ownership using 'chown -R root:root directory' including all subdirectories and file as it was expected.

Question: Why does the 'chown' command does not work recursively using the '-R' flag for directories owned by the user nobody? Why is it not possible to delete files owned by the user nobody as root?

Edit: In response to the comments I would like to provide the full name of 'pathToSecondWeirdDirectory'.

~/.local/share/Trash/expunged/294376611/5e5a7b41-3df4-4b2f-b7ac-f57d09ed1823/.sage/matplotlib-1.5.1

Another example

~/.local/share/Trash/expunged/294376611/5e5a7b41-3df4-4b2f-b7ac-f57d09ed1823/.sage/R

Edit 2: After Marcus has given a great answer, I did some more debugging using the same technique. Chowning a single directory works as expected. Chowning using -R fails. I've compared the outputs and the are identical until the last few lines. Here are they:

CHOWN:

close(8)                                = 0
close(5)                                = 0
close(6)                                = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
newfstatat(AT_FDCWD, "security", {st_mode=S_IFDIR|0700, st_size=4096, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchownat(AT_FDCWD, "security", 60202, 60202, 0) = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

CHOWN -R

close(8)                                = 0
close(5)                                = 0
close(6)                                = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
newfstatat(AT_FDCWD, "startup", {st_mode=S_IFDIR|0700, st_size=4096, ...}, AT_SYMLINK_NOFOLLOW) = 0
openat(AT_FDCWD, "startup", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = -1 EACCES (Permission denied)
openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=2998, ...}, AT_EMPTY_PATH) = 0
read(3, "# Locale name alias data base.\n#"..., 4096) = 2998
read(3, "", 4096)                       = 0
close(3)                                = 0
openat(AT_FDCWD, "/usr/share/locale/en_US.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_US.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_US/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, "chown: ", 7)                  = 7
write(2, "cannot read directory 'startup'", 31) = 31
openat(AT_FDCWD, "/usr/share/locale/en_US.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_US.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, ": Permission denied", 19)     = 19
write(2, "\n", 1)                       = 1
close(1)                                = 0
close(2)                                = 0
exit_group(1)                           = ?
+++ exited with 1 +++
17
  • 1
    Why were there directories owned by nobody in the first place? That use should not own anything on a system. Also, I'm much more interested in what provoked the "Value too large for defined data type" error, which I've never seen before.
    – Kusalananda
    Jan 5, 2022 at 12:00
  • Please post an example of the weird names, do they have spaces in them or special characters by any chance? Jan 5, 2022 at 12:02
  • 2
    My guess would be that the nobody:nobody results from the access of this location by networking, maybe samba or NFS, would this make any sense? Who or what is sage in your environment ? If they are a result of remote filesystem access, even root may not be able to change them from your system Jan 5, 2022 at 12:12
  • 2
    @DavidScholz weird for sure. Wait, can you run type rm for us? and if it's an executable with a path, file /path/to/rm? Jan 5, 2022 at 12:37
  • 1
    @DavidScholz, I don't actually know much about containers. I understand there's some functionality for UID mapping which sounds like it could be related, maybe, but really I was mostly just shooting in the dark.
    – ilkkachu
    Jan 6, 2022 at 11:39

2 Answers 2

3

Without more debugging¹, it's impossible to know for sure, but this sure looks like the stat/stat64 problem Linux had² (and still has).

Basically, there's the fstat syscall used to query things like "is this file a directory?" (which is very important to know if you're trying to recursively delete things), "is it a symlink?", "What's its size?".

And that last point's exactly where the fun begins: That syscall takes a pointer to a struct stat, which contains fields for all these kinds of information. And originally, the file size integer was 32 bit. Now, a file can be larger than that. So, there needed to be a new call that could give you that information as 64 bit number.

Now, what to do when you used the 32 bit stat variant on a file larger than what the 32 bit variable could hold? Clearly, there needed to be an error condition, so that you'd not accidentally think a 65 GB file was only 1 GB in size. And that error, when passed to error/strerror/perror prints exactly the error message you're seeing.

Of course, the same mechanism applies when other parts of the file stat don't fit in the type you want to return (or when the maximum page count is exceeded, and probably a couple other cases, too).

So, now comes the interesting part: it's very unlikely your relatively modern

/usr/bin/rm: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=5d1d8b77d21f9362855e93f8cff5fc685127a26f, for GNU/Linux 4.4.0, stripped

is using the old fstat[at] system call. You can try:

cd /tmp
touch base
strace -o log.strace -e /stat rm base
grep '"base"' log.strace

should probably yield calls to newfstatat, which definitely deals with 64 bit numbers.

So, equipped with this knowledge, we now try to delete one of your weird directories:

strace -o /tmp/log.strace rm -r /path/to/one/single_one/of/the/undeletable_directories

and scroll to the bottom of the log: There's going to be a few lines of calls needed to print the error message, but above that should be a call that yielded EOVERFLOW (hint: search for that string!). My hypothesis is that this is not a usual stat call, but quite possibly an openat call or something that fails for a different reason.


¹ I'd run gdb --args rm /path/to/weirddirectory, set a breakpoint on any call to error, and if that doesn't work, any call to write.

² There's even a Coreutils FAQ entry, archive.org link, since I don't trust the FSF to run dependable infrastructure forever

2
  • Thank you for this great answer! It introduces a new debugging technique which I haven't known yet. It seems that you are correct, there is indeed a syscall to 'openat' that fails. I did the same tracing using the 'chown -R' and 'chown' and compared the output and it was nearly identical. However, plain 'chown' succeeds while 'chown -R' did not. Chown the first directory, then chown its subdirectory succeeds as well, thus I've compared the traces and I posted the result in my answer. Does this tell you something? I've ended up chowning manually due to time constraints. Jan 6, 2022 at 9:34
  • Great answer... Btw, @MarcusMueller, I heartily endorse your profile quote about two days in a lab versus one hour reading... :) Apr 1, 2022 at 23:20
-1

Please consider that you might be traversing soft links in the recursive path.

Suggesting to try:

 chown -L -R me:me pathToSecondWeirdDirectory
 

It is possible to delete traversing symbolic link with find command

 find -L <target dir1> <target dir2> ... -delete
3
  • 1
    I would be very wary of using this until you understand where the links are pointing. As root you could really do some significant damage. Jan 5, 2022 at 13:22
  • 1
    Sadly, this is not a problem with symbolic links, thus your suggested method does not work. Jan 5, 2022 at 13:42
  • Why do you think it would have anything to do with symlinks?
    – ilkkachu
    Jan 5, 2022 at 15:35

You must log in to answer this question.

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