Skip to content

Commit

Permalink
utils: improve error message if path not executable
Browse files Browse the repository at this point in the history
improve the error returned when the specified path is not executable.

Return the reason why the lookup failed when the path is not a regular
file, or has no executable bit set.

Closes: #1671

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
  • Loading branch information
giuseppe committed Feb 14, 2025
1 parent 22443f7 commit 8f3e370
Showing 1 changed file with 47 additions and 16 deletions.
63 changes: 47 additions & 16 deletions src/libcrun/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -1849,30 +1849,52 @@ parse_json_file (yajl_val *out, const char *jsondata, struct parser_context *ctx
return 0;
}

#define CHECK_ACCESS_NOT_EXECUTABLE 1
#define CHECK_ACCESS_NOT_REGULAR 2

/* check that the specified path exists and it is executable.
Return
- 0 if the file is executable
- CHECK_ACCESS_NOT_EXECUTABLE if it exists but it is not executable
- CHECK_ACCESS_NOT_REGULAR if it not a regular file
- -errno for any other generic error
*/
static int
check_access (const char *path)
{
int ret;
mode_t mode;

#ifdef HAVE_EACCESS
ret = eaccess (path, X_OK);
# define ACCESS(path, mode) (eaccess (path, mode))
#else
ret = access (path, X_OK);
# define ACCESS(path, mode) (access (path, mode))
#endif

ret = ACCESS (path, X_OK);
if (ret < 0)
return ret;
{
/* If the file is not executable, check if it exists. */
if (errno == EACCES)
{
int saved_errno = errno;
ret = ACCESS (path, F_OK);
errno = saved_errno;

if (ret == 0)
return CHECK_ACCESS_NOT_EXECUTABLE;
}
return -errno;
}

ret = get_file_type (&mode, false, path);
if (UNLIKELY (ret < 0))
return ret;
return -errno;

if (! S_ISREG (mode))
{
errno = EPERM;
return -1;
}
return CHECK_ACCESS_NOT_REGULAR;

/* It exists, is executable and is a regular file. */
return 0;
}

Expand All @@ -1881,7 +1903,7 @@ find_executable (char **out, const char *executable_path, const char *cwd, libcr
{
cleanup_free char *cwd_executable_path = NULL;
cleanup_free char *tmp = NULL;
int last_error = ENOENT;
int last_error = -ENOENT;
char *it, *end;
int ret;

Expand Down Expand Up @@ -1918,6 +1940,7 @@ find_executable (char **out, const char *executable_path, const char *cwd, libcr
*out = xstrdup (executable_path);
return 0;
}
last_error = ret;
goto fail;
}

Expand Down Expand Up @@ -1946,19 +1969,27 @@ find_executable (char **out, const char *executable_path, const char *cwd, libcr
return 0;
}

if (errno == ENOENT)
if (ret == -ENOENT)
continue;

last_error = errno;
last_error = ret;
}

errno = last_error;

fail:
if (errno == ENOENT)
return crun_make_error (err, errno, "cannot find executable `%s`", executable_path);
switch (last_error)
{
case CHECK_ACCESS_NOT_EXECUTABLE:
return crun_make_error (err, EPERM, "the path `%s` exists but it is not executable", executable_path);

case CHECK_ACCESS_NOT_REGULAR:
return crun_make_error (err, EPERM, "the path `%s` is not a regular file", executable_path);

return crun_make_error (err, errno, "cannot open `%s`", executable_path);
default:
errno = -last_error;
if (errno == ENOENT)
return crun_make_error (err, errno, "cannot find executable `%s`", executable_path);
return crun_make_error (err, errno, "cannot open `%s`", executable_path);
}
}

#ifdef HAVE_FGETXATTR
Expand Down

0 comments on commit 8f3e370

Please sign in to comment.