Revert "Don’t silently truncate file names in exec.c"

This reverts commit 3461b450c5.

Gnulib and intprops.h are not available from within the exec helper.
This commit is contained in:
Po Lu 2026-05-25 11:21:00 +08:00
parent b72dcebdab
commit 44013f6be7
2 changed files with 49 additions and 49 deletions

View file

@ -863,25 +863,32 @@ insert_args (struct exec_tracee *tracee, USER_REGS_STRUCT *regs,
/* Format PID, a nonnegative process identifier, in base 10.
Place the result in *IN. Do not null-terminate the result.
Possibly modify the bytes in IN that are after the result.
Return a pointer to the byte after the result. */
/* Format PID, an unsigned process identifier, in base 10. Place the
result in *IN, and return a pointer to the byte after the
result. REM should be NULL. */
char *
format_pid (char in[INT_STRLEN_BOUND (pid_t)], pid_t pid)
format_pid (char *in, unsigned int pid)
{
char *pend = in + INT_STRLEN_BOUND (pid_t);
char *p = pend;
unsigned int digits[32], *fill;
do
*--p = '0' + pid % 10;
while ((pid /= 10) != 0);
fill = digits;
do
*in++ = *p++;
while (p < pend);
for (; pid != 0; pid = pid / 10)
*fill++ = pid % 10;
/* Insert 0 if the number would otherwise be empty. */
if (fill == digits)
*fill++ = 0;
while (fill != digits)
{
--fill;
*in++ = '0' + *fill;
}
*in = '\0';
return in;
}
@ -897,13 +904,10 @@ format_pid (char in[INT_STRLEN_BOUND (pid_t)], pid_t pid)
Finally, use REGS to add the required interpreter arguments to the
caller's argv.
NAME must be a null-terminated string in a buffer of size PATH_MAX.
It might be updated to be a string no longer than PATH_MAX - 1.
Value is NULL upon failure, with errno set accordingly. */
char *
exec_0 (char name[PATH_MAX], struct exec_tracee *tracee,
exec_0 (char *name, struct exec_tracee *tracee,
size_t *size, USER_REGS_STRUCT *regs)
{
int fd, rc, i;
@ -912,13 +916,14 @@ exec_0 (char name[PATH_MAX], struct exec_tracee *tracee,
program_header program;
USER_WORD entry, program_entry, offset;
USER_WORD header_offset;
ptrdiff_t nlen;
USER_WORD name_len, aligned_len;
struct exec_jump_command jump;
/* This also encompasses !__LP64__. */
#if defined __mips__ && !defined MIPS_NABI
int fpu_mode;
#endif /* defined __mips__ && !defined MIPS_NABI */
char buffer[80], buffer1[PATH_MAX + 80], *rewrite;
ssize_t link_size;
size_t remaining;
/* If the process is trying to run /proc/self/exe, make it run
@ -926,13 +931,8 @@ exec_0 (char name[PATH_MAX], struct exec_tracee *tracee,
if (!strcmp (name, "/proc/self/exe") && tracee->exec_file)
{
nlen = strnlen (tracee->exec_file, PATH_MAX);
if (PATH_MAX <= nlen)
{
errno = ENAMETOOLONG;
return NULL;
}
memcpy (name, tracee->exec_file, nlen + 1);
strncpy (name, tracee->exec_file, PATH_MAX - 1);
name[PATH_MAX] = '\0';
}
else
{
@ -940,45 +940,45 @@ exec_0 (char name[PATH_MAX], struct exec_tracee *tracee,
cwd. Do not use sprintf at it is not reentrant and it
mishandles results longer than INT_MAX. */
nlen = strlen (name);
if (name[0] && name[0] != '/')
{
char buffer[sizeof "/proc//cwd" + INT_STRLEN_BOUND (pid_t)];
char buffer1[PATH_MAX];
/* Clear both buffers. */
memset (buffer, 0, sizeof buffer);
memset (buffer1, 0, sizeof buffer1);
/* Copy over "/proc/", the PID, and "/cwd". */
char *rewrite = stpcpy (buffer, "/proc/");
/* Copy over /proc, the PID, and /cwd/. */
rewrite = stpcpy (buffer, "/proc/");
rewrite = format_pid (rewrite, tracee->pid);
strcpy (rewrite, "/cwd");
/* Resolve this symbolic link. */
ssize_t link_size = readlink (buffer, buffer1, sizeof buffer1);
link_size = readlink (buffer, buffer1,
PATH_MAX + 1);
if (link_size < 0)
return NULL;
/* Check that the link is reasonable. */
/* Check that the name is a reasonable size. */
if (link_size == 0 || buffer1[0] != '/')
{
errno = EINVAL;
return NULL;
}
ptrdiff_t link_len = link_size - (buffer1[link_size - 1] == '/');
if (PATH_MAX <= link_len + 1 + nlen)
if (link_size > PATH_MAX)
{
/* The name is too long. */
errno = ENAMETOOLONG;
return NULL;
}
/* Replace name with link contents,
then '/' if needed, then name. */
memmove (name + link_len + 1, name, nlen + 1);
memcpy (name, buffer1, link_len);
name[link_len] = '/';
nlen += link_len + 1;
/* Add a directory separator if necessary. */
if (!link_size || buffer1[link_size - 1] != '/')
buffer1[link_size] = '/', link_size++;
rewrite = buffer1 + link_size;
remaining = buffer1 + sizeof buffer1 - rewrite - 1;
memcpy (rewrite, name, strnlen (name, remaining));
/* Replace name with buffer1. */
strcpy (name, buffer1);
}
}
@ -1151,7 +1151,7 @@ exec_0 (char name[PATH_MAX], struct exec_tracee *tracee,
loader_area_used += sizeof jump;
/* Copy the length of NAME and NAME itself to the loader area. */
name_len = nlen;
name_len = strlen (name);
aligned_len = ((name_len + 1 + sizeof name_len - 1)
& -sizeof name_len);
if (sizeof loader_area - loader_area_used

View file

@ -732,7 +732,7 @@ check_signal (struct exec_tracee *tracee, int status)
static int
handle_exec (struct exec_tracee *tracee, USER_REGS_STRUCT *regs)
{
char buffer[PATH_MAX], *area;
char buffer[PATH_MAX + 80], *area;
USER_REGS_STRUCT original;
size_t size, loader_size;
USER_WORD loader;