cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

execvp.c (4099B)


      1/* Copyright (C) 2006 by Paolo Giarrusso - modified from glibc' execvp.c.
      2   Original copyright notice follows:
      3
      4   Copyright (C) 1991,92,1995-99,2002,2004 Free Software Foundation, Inc.
      5   This file is part of the GNU C Library.
      6
      7   The GNU C Library is free software; you can redistribute it and/or
      8   modify it under the terms of the GNU Lesser General Public
      9   License as published by the Free Software Foundation; either
     10   version 2.1 of the License, or (at your option) any later version.
     11
     12   The GNU C Library is distributed in the hope that it will be useful,
     13   but WITHOUT ANY WARRANTY; without even the implied warranty of
     14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15   Lesser General Public License for more details.
     16
     17   You should have received a copy of the GNU Lesser General Public
     18   License along with the GNU C Library; if not, write to the Free
     19   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     20   02111-1307 USA.  */
     21#include <unistd.h>
     22
     23#include <stdbool.h>
     24#include <stdlib.h>
     25#include <string.h>
     26#include <errno.h>
     27#include <limits.h>
     28
     29#ifndef TEST
     30#include <um_malloc.h>
     31#else
     32#include <stdio.h>
     33#define um_kmalloc malloc
     34#endif
     35#include <os.h>
     36
     37/* Execute FILE, searching in the `PATH' environment variable if it contains
     38   no slashes, with arguments ARGV and environment from `environ'.  */
     39int execvp_noalloc(char *buf, const char *file, char *const argv[])
     40{
     41	if (*file == '\0') {
     42		return -ENOENT;
     43	}
     44
     45	if (strchr (file, '/') != NULL) {
     46		/* Don't search when it contains a slash.  */
     47		execv(file, argv);
     48	} else {
     49		int got_eacces;
     50		size_t len, pathlen;
     51		char *name, *p;
     52		char *path = getenv("PATH");
     53		if (path == NULL)
     54			path = ":/bin:/usr/bin";
     55
     56		len = strlen(file) + 1;
     57		pathlen = strlen(path);
     58		/* Copy the file name at the top.  */
     59		name = memcpy(buf + pathlen + 1, file, len);
     60		/* And add the slash.  */
     61		*--name = '/';
     62
     63		got_eacces = 0;
     64		p = path;
     65		do {
     66			char *startp;
     67
     68			path = p;
     69			//Let's avoid this GNU extension.
     70			//p = strchrnul (path, ':');
     71			p = strchr(path, ':');
     72			if (!p)
     73				p = strchr(path, '\0');
     74
     75			if (p == path)
     76				/* Two adjacent colons, or a colon at the beginning or the end
     77				   of `PATH' means to search the current directory.  */
     78				startp = name + 1;
     79			else
     80				startp = memcpy(name - (p - path), path, p - path);
     81
     82			/* Try to execute this name.  If it works, execv will not return.  */
     83			execv(startp, argv);
     84
     85			/*
     86			if (errno == ENOEXEC) {
     87			}
     88			*/
     89
     90			switch (errno) {
     91				case EACCES:
     92					/* Record the we got a `Permission denied' error.  If we end
     93					   up finding no executable we can use, we want to diagnose
     94					   that we did find one but were denied access.  */
     95					got_eacces = 1;
     96					break;
     97				case ENOENT:
     98				case ESTALE:
     99				case ENOTDIR:
    100					/* Those errors indicate the file is missing or not executable
    101					   by us, in which case we want to just try the next path
    102					   directory.  */
    103				case ENODEV:
    104				case ETIMEDOUT:
    105					/* Some strange filesystems like AFS return even
    106					   stranger error numbers.  They cannot reasonably mean
    107					   anything else so ignore those, too.  */
    108				case ENOEXEC:
    109					/* We won't go searching for the shell
    110					 * if it is not executable - the Linux
    111					 * kernel already handles this enough,
    112					 * for us. */
    113					break;
    114
    115				default:
    116					/* Some other error means we found an executable file, but
    117					   something went wrong executing it; return the error to our
    118					   caller.  */
    119					return -errno;
    120			}
    121		} while (*p++ != '\0');
    122
    123		/* We tried every element and none of them worked.  */
    124		if (got_eacces)
    125			/* At least one failure was due to permissions, so report that
    126			   error.  */
    127			return -EACCES;
    128	}
    129
    130	/* Return the error from the last attempt (probably ENOENT).  */
    131	return -errno;
    132}
    133#ifdef TEST
    134int main(int argc, char**argv)
    135{
    136	char buf[PATH_MAX];
    137	int ret;
    138	argc--;
    139	if (!argc) {
    140		os_warn("Not enough arguments\n");
    141		return 1;
    142	}
    143	argv++;
    144	if (ret = execvp_noalloc(buf, argv[0], argv)) {
    145		errno = -ret;
    146		perror("execvp_noalloc");
    147	}
    148	return 0;
    149}
    150#endif