Skip to content

Commit 400caaf

Browse files
Clément Chigotgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ee662bf commit 400caaf

File tree

5 files changed

+52
-2
lines changed

5 files changed

+52
-2
lines changed

Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,9 @@ all::
439439
#
440440
# Define FILENO_IS_A_MACRO if fileno() is a macro, not a real function.
441441
#
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+
#
442445
# Define PAGER_ENV to a SP separated VAR=VAL pairs to define
443446
# default environment variables to be passed when a pager is spawned, e.g.
444447
#
@@ -1815,6 +1818,11 @@ ifdef FILENO_IS_A_MACRO
18151818
COMPAT_OBJS += compat/fileno.o
18161819
endif
18171820

1821+
ifdef NEED_ACCESS_ROOT_HANDLER
1822+
COMPAT_CFLAGS += -DNEED_ACCESS_ROOT_HANDLER
1823+
COMPAT_OBJS += compat/access.o
1824+
endif
1825+
18181826
ifeq ($(TCLTK_PATH),)
18191827
NO_TCLTK = NoThanks
18201828
endif

compat/access.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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+
}

compat/fileno.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#define COMPAT_CODE
1+
#define COMPAT_CODE_FILENO
22
#include "../git-compat-util.h"
33

44
int git_fileno(FILE *stream)

config.mak.uname

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ ifeq ($(uname_S),AIX)
270270
NEEDS_LIBICONV = YesPlease
271271
BASIC_CFLAGS += -D_LARGE_FILES
272272
FILENO_IS_A_MACRO = UnfortunatelyYes
273+
NEED_ACCESS_ROOT_HANDLER = UnfortunatelyYes
273274
ifeq ($(shell expr "$(uname_V)" : '[1234]'),1)
274275
NO_PTHREADS = YesPlease
275276
else

git-compat-util.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1236,12 +1236,22 @@ struct tm *git_gmtime_r(const time_t *, struct tm *);
12361236

12371237
#ifdef FILENO_IS_A_MACRO
12381238
int git_fileno(FILE *stream);
1239-
# ifndef COMPAT_CODE
1239+
# ifndef COMPAT_CODE_FILENO
12401240
# undef fileno
12411241
# define fileno(p) git_fileno(p)
12421242
# endif
12431243
#endif
12441244

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)
1252+
# endif
1253+
#endif
1254+
12451255
/*
12461256
* Our code often opens a path to an optional file, to work on its
12471257
* contents when we can successfully open it. We can ignore a failure

0 commit comments

Comments
 (0)