Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > gnu.bash.bug > #14964

Re: difference between /tmp and other directory for loadable mkdir?

From Eduardo A. Bustamante López <dualbus@gmail.com>
Newsgroups gnu.bash.bug
Subject Re: difference between /tmp and other directory for loadable mkdir?
Date 2018-12-26 11:56 -0800
Message-ID <mailman.6330.1545854186.1284.bug-bash@gnu.org> (permalink)
References <CABrM6wmWnNA0PZmdd=C5Y1-ABSJ_beHdY4V5NSzgZROUCUP5WQ@mail.gmail.com>

Show all headers | View raw


On Wed, Dec 26, 2018 at 12:40:09PM -0600, Peng Yu wrote:
> Hi,
> 
> I can not mkdir -p . in /tmp/ via the loadable mkdir. What is the
> difference between /tmp/ and other directories? I am on Mac OS X. Is
> this a bug in mkdir?
> 
> $ cd /tmp
> $ mkdir -p -- .
> -bash: mkdir: .: Operation not permitted

I can reproduce this in Linux
[Linux debian 4.18.0-3-amd64 #1 SMP Debian 4.18.20-2 (2018-11-23) x86_64 GNU/Linux]

dualbus@debian:~/src/gnu/bash$ strace -e trace=%file -f ./bash -c 'enable -f examples/loadables/mkdir mkdir && mkdir -p -- /tmp'
execve("./bash", ["./bash", "-c", "enable -f examples/loadables/mkd"...], 0x7fff7c9b1c18 /* 33 vars */) = 0
(...)
stat("/home/dualbus/src/gnu/bash", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat(".", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("/home", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("/home/dualbus", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("/home/dualbus/src", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("/home/dualbus/src/gnu", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("/home/dualbus/src/gnu/bash", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("/home/dualbus/src/iovisor/bcc", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
openat(AT_FDCWD, "examples/loadables/mkdir", O_RDONLY|O_CLOEXEC) = 3
getcwd("/home/dualbus/src/gnu/bash", 128) = 27
stat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=4096, ...}) = 0
chmod("/tmp", 0755)                     = -1 EPERM (Operation not permitted)
openat(AT_FDCWD, "/usr/share/locale/en_CA/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)
openat(AT_FDCWD, "/usr/local/share/locale/en_CA/LC_MESSAGES/bash.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/local/share/locale/en/LC_MESSAGES/bash.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
./bash: line 0: mkdir: /tmp: Operation not permitted
+++ exited with 1 +++

dualbus@debian:~/src/gnu/bash$ stat /tmp
  File: /tmp
  Size: 4096      	Blocks: 8          IO Block: 4096   directory
Device: fe01h/65025d	Inode: 25427969    Links: 18
Access: (1777/drwxrwxrwt)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2018-12-26 11:08:30.062681076 -0800
Modify: 2018-12-26 11:37:56.826984422 -0800
Change: 2018-12-26 11:37:56.826984422 -0800
 Birth: -


If you look at the source, it calls the mkdir() function to create the directory.

dualbus@debian:~/src/gnu/bash$ cat -n examples/loadables/mkdir.c | sed -n '174,180p'
   174	      if (stat (npath, &sb) != 0)
   175		{
   176		  if (mkdir (npath, parent_mode))  <- this
   177		    {
   178		      builtin_error ("cannot create directory `%s': %s", npath, strerror (errno));
   179		      umask (original_umask);
   180		      free (npath);

Ref: http://git.savannah.gnu.org/cgit/bash.git/tree/examples/loadables/mkdir.c?h=6870125961b85baa9628ce4c5fbbca94e8046656#n174


Comparing to GNU coreutils' mkdir (which uses gnulib):

dualbus@debian:~$ strace -e trace=%file -f mkdir -p /tmp/
execve("/bin/mkdir", ["mkdir", "-p", "/tmp/"], 0x7fff4f7a11b8 /* 33 vars */) = 0
(...)
mkdir("/tmp/", 0777)                    = -1 EEXIST (File exists)
stat("/tmp/", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=4096, ...}) = 0
+++ exited with 0 +++


My guess is that the "problem" has to do with how bash computes the `parent_mode':

dualbus@debian:~/src/gnu/bash$ cat -n examples/loadables/mkdir.c | sed -n '106,114p'
   106	  /* Make the new mode */
   107	  original_umask = umask (0);
   108	  umask (original_umask);
   109	
   110	  nmode = (S_IRWXU | S_IRWXG | S_IRWXO) & ~original_umask;
   111	  parent_mode = nmode | (S_IWUSR|S_IXUSR);	/* u+wx */
   112	
   113	  /* Adjust new mode based on mode argument */
   114	  nmode &= omode;

Ref: http://git.savannah.gnu.org/cgit/bash.git/tree/examples/loadables/mkdir.c?h=6870125961b85baa9628ce4c5fbbca94e8046656#n106


In gnulib, this is what is used to create the parent directories:

Ref: http://git.savannah.gnu.org/cgit/gnulib.git/tree/lib/mkdir-p.c?h=95c96b6dddd31f3676f72ed044d0c493ab5642d8#n116

Back to gnu.bash.bug | Previous | Next | Find similar | Unroll thread


Thread

Re: difference between /tmp and other directory for loadable mkdir? Eduardo A. Bustamante López <dualbus@gmail.com> - 2018-12-26 11:56 -0800

csiph-web