Git fork

git-compat-util: work around for access(X_OK) under root

On AIX, access(X_OK) may succeed when run as root even if the
execution isn't possible. This behavior is allowed by POSIX
which says:

... for a process with appropriate privileges, an implementation
may indicate success for X_OK even if execute permission is not
granted to any user.

It can lead hook programs to have their execution refused:

git commit -m content
fatal: cannot exec '.git/hooks/pre-commit': Permission denied

Add NEED_ACCESS_ROOT_HANDLER in order to use an access helper function.
It checks with stat if any executable flags is set when the current user
is root.

Signed-off-by: Clément Chigot <clement.chigot@atos.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Clément Chigot and committed by
Junio C Hamano
400caafb ee662bf5

+52 -2
+8
Makefile
··· 439 439 # 440 440 # Define FILENO_IS_A_MACRO if fileno() is a macro, not a real function. 441 441 # 442 + # Define NEED_ACCESS_ROOT_HANDLER if access() under root may success for X_OK 443 + # even if execution permission isn't granted for any user. 444 + # 442 445 # Define PAGER_ENV to a SP separated VAR=VAL pairs to define 443 446 # default environment variables to be passed when a pager is spawned, e.g. 444 447 # ··· 1813 1816 ifdef FILENO_IS_A_MACRO 1814 1817 COMPAT_CFLAGS += -DFILENO_IS_A_MACRO 1815 1818 COMPAT_OBJS += compat/fileno.o 1819 + endif 1820 + 1821 + ifdef NEED_ACCESS_ROOT_HANDLER 1822 + COMPAT_CFLAGS += -DNEED_ACCESS_ROOT_HANDLER 1823 + COMPAT_OBJS += compat/access.o 1816 1824 endif 1817 1825 1818 1826 ifeq ($(TCLTK_PATH),)
+31
compat/access.c
··· 1 + #define COMPAT_CODE_ACCESS 2 + #include "../git-compat-util.h" 3 + 4 + /* Do the same thing access(2) does, but use the effective uid, 5 + * and don't make the mistake of telling root that any file is 6 + * executable. This version uses stat(2). 7 + */ 8 + int git_access(const char *path, int mode) 9 + { 10 + struct stat st; 11 + 12 + /* do not interfere a normal user */ 13 + if (geteuid()) 14 + return access(path, mode); 15 + 16 + if (stat(path, &st) < 0) 17 + return -1; 18 + 19 + /* Root can read or write any file. */ 20 + if (!(mode & X_OK)) 21 + return 0; 22 + 23 + /* Root can execute any file that has any one of the execute 24 + * bits set. 25 + */ 26 + if (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) 27 + return 0; 28 + 29 + errno = EACCES; 30 + return -1; 31 + }
+1 -1
compat/fileno.c
··· 1 - #define COMPAT_CODE 1 + #define COMPAT_CODE_FILENO 2 2 #include "../git-compat-util.h" 3 3 4 4 int git_fileno(FILE *stream)
+1
config.mak.uname
··· 270 270 NEEDS_LIBICONV = YesPlease 271 271 BASIC_CFLAGS += -D_LARGE_FILES 272 272 FILENO_IS_A_MACRO = UnfortunatelyYes 273 + NEED_ACCESS_ROOT_HANDLER = UnfortunatelyYes 273 274 ifeq ($(shell expr "$(uname_V)" : '[1234]'),1) 274 275 NO_PTHREADS = YesPlease 275 276 else
+11 -1
git-compat-util.h
··· 1236 1236 1237 1237 #ifdef FILENO_IS_A_MACRO 1238 1238 int git_fileno(FILE *stream); 1239 - # ifndef COMPAT_CODE 1239 + # ifndef COMPAT_CODE_FILENO 1240 1240 # undef fileno 1241 1241 # define fileno(p) git_fileno(p) 1242 + # endif 1243 + #endif 1244 + 1245 + #ifdef NEED_ACCESS_ROOT_HANDLER 1246 + int git_access(const char *path, int mode); 1247 + # ifndef COMPAT_CODE_ACCESS 1248 + # ifdef access 1249 + # undef access 1250 + # endif 1251 + # define access(path, mode) git_access(path, mode) 1242 1252 # endif 1243 1253 #endif 1244 1254