VirtualBox

Changeset 57869 in vbox


Ignore:
Timestamp:
Sep 23, 2015 1:53:53 PM (9 years ago)
Author:
vboxsync
Message:

process-creation-posix.cpp: Hacked up support for RTPROC_FLAGS_PROFILE and RTPROC_FLAGS_ENV_CHANGE_RECORD. Works on my linux.

Location:
trunk/src/VBox/Runtime
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/posix/process-creation-posix.cpp

    r57358 r57869  
    4141#include <signal.h>
    4242#include <grp.h>
     43#include <paths.h>
     44#include <pwd.h>
    4345#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
    4446# include <crypt.h>
    45 # include <pwd.h>
    4647# include <shadow.h>
    4748#endif
     
    103104    pw = getpwnam(pszUser);
    104105    if (!pw)
    105         return VERR_PERMISSION_DENIED;
     106        return VERR_AUTHENTICATION_FAILURE;
    106107
    107108    if (!pszPasswd)
     
    127128    }
    128129    if (!fCorrect)
    129         return VERR_PERMISSION_DENIED;
     130        return VERR_AUTHENTICATION_FAILURE;
    130131
    131132    *pGid = pw->pw_gid;
     
    138139
    139140    if (getpwnam_r(pszUser, &pw, szBuf, sizeof(szBuf), &ppw) != 0 || ppw == NULL)
    140         return VERR_PERMISSION_DENIED;
     141        return VERR_AUTHENTICATION_FAILURE;
    141142
    142143    if (!pszPasswd)
     
    151152    char *pszEncPasswd = crypt(pszPasswd, ppw->pw_passwd);
    152153    if (strcmp(pszEncPasswd, ppw->pw_passwd))
    153         return VERR_PERMISSION_DENIED;
     154        return VERR_AUTHENTICATION_FAILURE;
    154155
    155156    *pGid = ppw->pw_gid;
     
    159160#else
    160161    NOREF(pszUser); NOREF(pszPasswd); NOREF(pGid); NOREF(pUid);
    161     return VERR_PERMISSION_DENIED;
     162    return VERR_AUTHENTICATION_FAILURE;
    162163#endif
    163164}
     
    271272                          NULL /*pszAsUser*/, NULL /* pszPassword*/,
    272273                          pProcess);
     274}
     275
     276
     277/**
     278 * Adjust the profile environment after forking the child process and changing
     279 * the UID.
     280 *
     281 * @returns IRPT status code.
     282 * @param   hEnvToUse       The environment we're going to use with execve.
     283 * @param   fFlags          The process creation flags.
     284 * @param   hEnv            The environment passed in by the user.
     285 */
     286static int rtProcPosixAdjustProfileEnvFromChild(RTENV hEnvToUse, uint32_t fFlags, RTENV hEnv)
     287{
     288    int rc = VINF_SUCCESS;
     289#ifdef RT_OS_DARWIN
     290    if (   RT_SUCCESS(rc)
     291        && (!(fFlags & RTPROC_FLAGS_ENV_CHANGE_RECORD) || RTEnvExistEx(hEnv, "TMPDIR")) )
     292    {
     293        char szValue[_4K];
     294        rc = confstr(_SC_DARWIN_USER_TEMP_DIR, szValue, sizeof(szValue));
     295        if (rc > 0 && rc < sizeof(szValue))
     296        {
     297            char *pszTmp
     298            rc = RTStrCurrentCPToUtf8(&pszTmp, achBuf);
     299            if (RT_SUCCESS(rc))
     300            {
     301                rc = RTEnvSetEx(hEnvToUse, "TMPDIR", pszTmp);
     302                RTStrFree(pszTmp);
     303            }
     304        }
     305        else
     306            rc = VERR_BUFFER_OVERFLOW;
     307    }
     308#endif
     309    return rc;
     310}
     311
     312
     313/**
     314 * Create a very very basic environment for a user.
     315 *
     316 * @returns IPRT status code.
     317 * @param   phEnvToUse  Where to return the created environment.
     318 * @param   pszUser     The user name for the profile.
     319 */
     320static int rtProcPosixCreateProfileEnv(PRTENV phEnvToUse, const char *pszUser)
     321{
     322    struct passwd   Pwd;
     323    struct passwd  *pPwd = NULL;
     324    char            achBuf[_4K];
     325    int             rc;
     326    errno = 0;
     327    if (pszUser)
     328        rc = getpwnam_r(pszUser, &Pwd, achBuf, sizeof(achBuf), &pPwd);
     329    else
     330        rc = getpwuid_r(getuid(), &Pwd, achBuf, sizeof(achBuf), &pPwd);
     331    if (rc == 0 && pPwd)
     332    {
     333        char *pszDir;
     334        rc = RTStrCurrentCPToUtf8(&pszDir, pPwd->pw_dir);
     335        if (RT_SUCCESS(rc))
     336        {
     337            char *pszShell;
     338            rc = RTStrCurrentCPToUtf8(&pszShell, pPwd->pw_shell);
     339            if (RT_SUCCESS(rc))
     340            {
     341                char *pszUserFree = NULL;
     342                if (!pszUser)
     343                {
     344                    rc = RTStrCurrentCPToUtf8(&pszUserFree, pPwd->pw_name);
     345                    if (RT_SUCCESS(rc))
     346                        pszUser = pszUserFree;
     347                }
     348                if (RT_SUCCESS(rc))
     349                {
     350                    rc = RTEnvCreate(phEnvToUse);
     351                    if (RT_SUCCESS(rc))
     352                    {
     353                        RTENV hEnvToUse = *phEnvToUse;
     354
     355                        rc = RTEnvSetEx(hEnvToUse, "HOME", pszDir);
     356                        if (RT_SUCCESS(rc))
     357                            rc = RTEnvSetEx(hEnvToUse, "SHELL", pszShell);
     358                        if (RT_SUCCESS(rc))
     359                            rc = RTEnvSetEx(hEnvToUse, "USER", pszUser);
     360                        if (RT_SUCCESS(rc))
     361                            rc = RTEnvSetEx(hEnvToUse, "LOGNAME", pszUser);
     362
     363                        if (RT_SUCCESS(rc))
     364                            rc = RTEnvSetEx(hEnvToUse, "PATH", pPwd->pw_uid == 0 ? _PATH_STDPATH : _PATH_DEFPATH);
     365
     366                        if (RT_SUCCESS(rc))
     367                        {
     368                            RTStrPrintf(achBuf, sizeof(achBuf), "%s/%s", _PATH_MAILDIR, pszUser);
     369                            rc = RTEnvSetEx(hEnvToUse, "MAIL", achBuf);
     370                        }
     371
     372#ifdef RT_OS_DARWIN
     373                        if (RT_SUCCESS(rc) && !pszUserFree)
     374                        {
     375                            rc = confstr(_SC_DARWIN_USER_TEMP_DIR, achBuf, sizeof(achBuf));
     376                            if (rc > 0 && rc < sizeof(achBuf))
     377                            {
     378                                char *pszTmp
     379                                rc = RTStrCurrentCPToUtf8(&pszTmp, achBuf);
     380                                if (RT_SUCCESS(rc))
     381                                {
     382                                    rc = RTEnvSetEx(hEnvToUse, "TMPDIR", pszTmp);
     383                                    RTStrFree(pszTmp);
     384                                }
     385                            }
     386                            else
     387                                rc = VERR_BUFFER_OVERFLOW;
     388                        }
     389#endif
     390
     391                        /** @todo load /etc/environment, /etc/profile.env and ~/.pam_environment? */
     392
     393                        if (RT_FAILURE(rc))
     394                            RTEnvDestroy(hEnvToUse);
     395                    }
     396                    RTStrFree(pszUserFree);
     397                }
     398                RTStrFree(pszShell);
     399            }
     400            RTStrFree(pszDir);
     401        }
     402    }
     403    else
     404        rc = errno ? RTErrConvertFromErrno(errno) : VERR_ACCESS_DENIED;
     405    return rc;
    273406}
    274407
     
    292425}
    293426
     427/**
     428 * Cleans up the environment on the way out.
     429 */
     430static int rtProcPosixCreateReturn(int rc, RTENV hEnvToUse, RTENV hEnv)
     431{
     432    if (hEnvToUse != hEnv)
     433        RTEnvDestroy(hEnvToUse);
     434    return rc;
     435}
     436
    294437
    295438RTR3DECL(int)   RTProcCreateEx(const char *pszExec, const char * const *papszArgs, RTENV hEnv, uint32_t fFlags,
     
    307450    AssertReturn(!(fFlags & RTPROC_FLAGS_DETACHED) || !phProcess, VERR_INVALID_PARAMETER);
    308451    AssertReturn(hEnv != NIL_RTENV, VERR_INVALID_PARAMETER);
    309     const char * const *papszEnv = RTEnvGetExecEnvP(hEnv);
    310     AssertPtrReturn(papszEnv, VERR_INVALID_HANDLE);
    311452    AssertPtrReturn(papszArgs, VERR_INVALID_PARAMETER);
    312     /** @todo search the PATH (add flag for this). */
    313453    AssertPtrNullReturn(pszAsUser, VERR_INVALID_POINTER);
    314454    AssertReturn(!pszAsUser || *pszAsUser, VERR_INVALID_PARAMETER);
     
    379519
    380520    /*
     521     * Create the child environment if either RTPROC_FLAGS_PROFILE or
     522     * RTPROC_FLAGS_ENV_CHANGE_RECORD are in effect.
     523     */
     524    RTENV hEnvToUse = hEnv;
     525    if (   (fFlags & (RTPROC_FLAGS_ENV_CHANGE_RECORD | RTPROC_FLAGS_PROFILE))
     526        && (   (fFlags & RTPROC_FLAGS_ENV_CHANGE_RECORD)
     527            || hEnv == RTENV_DEFAULT) )
     528    {
     529        if (fFlags & RTPROC_FLAGS_PROFILE)
     530            rc = rtProcPosixCreateProfileEnv(&hEnvToUse, pszAsUser);
     531        else
     532            rc = RTEnvClone(&hEnvToUse, RTENV_DEFAULT);
     533        if (RT_SUCCESS(rc))
     534        {
     535            if ((fFlags & RTPROC_FLAGS_ENV_CHANGE_RECORD) && hEnv != RTENV_DEFAULT)
     536                rc = RTEnvApplyChanges(hEnvToUse, hEnv);
     537            if (RT_FAILURE(rc))
     538                RTEnvDestroy(hEnvToUse);
     539        }
     540        if (RT_FAILURE(rc))
     541            return rc;
     542    }
     543
     544    /*
    381545     * Check for execute access to the file.
    382546     */
     
    384548    if (access(pszExec, X_OK))
    385549    {
     550        rc = errno;
    386551        if (   !(fFlags & RTPROC_FLAGS_SEARCH_PATH)
    387             || errno != ENOENT
     552            || rc != ENOENT
    388553            || RTPathHavePath(pszExec) )
    389             return RTErrConvertFromErrno(errno);
    390 
    391         /* search */
    392         char *pszPath = RTEnvDupEx(hEnv, "PATH");
    393         rc = RTPathTraverseList(pszPath, ':', rtPathFindExec, (void *)pszExec, &szRealExec[0]);
    394         RTStrFree(pszPath);
     554            rc = RTErrConvertFromErrno(rc);
     555        else
     556        {
     557            /* search */
     558            char *pszPath = RTEnvDupEx(hEnvToUse, "PATH");
     559            rc = RTPathTraverseList(pszPath, ':', rtPathFindExec, (void *)pszExec, &szRealExec[0]);
     560            RTStrFree(pszPath);
     561            if (RT_SUCCESS(rc))
     562                pszExec = szRealExec;
     563            else
     564                rc = rc == VERR_END_OF_STRING ? VERR_FILE_NOT_FOUND : rc;
     565        }
     566
    395567        if (RT_FAILURE(rc))
    396             return rc == VERR_END_OF_STRING ? VERR_FILE_NOT_FOUND : rc;
    397         pszExec = szRealExec;
     568            return rtProcPosixCreateReturn(rc, hEnvToUse, hEnv);
    398569    }
    399570
    400571    pid_t pid = -1;
     572    const char * const *papszEnv = RTEnvGetExecEnvP(hEnvToUse);
     573    AssertPtrReturn(papszEnv, rtProcPosixCreateReturn(VERR_INVALID_HANDLE, hEnvToUse, hEnv));
     574
    401575
    402576    /*
     
    418592            templateFd = rtSolarisContractPreFork();
    419593            if (templateFd == -1)
    420                 return VERR_OPEN_FAILED;
     594                return rtProcPosixCreateReturn(VERR_OPEN_FAILED, hEnvToUse, hEnv);
    421595        }
    422596# endif /* RT_OS_SOLARIS */
     
    427601            if (!(fFlags & RTPROC_FLAGS_SAME_CONTRACT))
    428602                rtSolarisContractPostForkChild(templateFd);
    429 # endif /* RT_OS_SOLARIS */
     603# endif
    430604            setsid(); /* see comment above */
    431605
     
    435609        else
    436610        {
    437 #ifdef RT_OS_SOLARIS
     611# ifdef RT_OS_SOLARIS
    438612            if (!(fFlags & RTPROC_FLAGS_SAME_CONTRACT))
    439613                rtSolarisContractPostForkParent(templateFd, pid);
    440 #endif /* RT_OS_SOLARIS */
     614# endif
    441615            if (pid > 0)
    442616            {
     
    454628                /* Assume that something wasn't found. No detailed info. */
    455629                if (status)
    456                     return VERR_PROCESS_NOT_FOUND;
     630                    return rtProcPosixCreateReturn(VERR_PROCESS_NOT_FOUND, hEnvToUse, hEnv);
    457631                if (phProcess)
    458632                    *phProcess = 0;
    459                 return VINF_SUCCESS;
    460             }
    461             return RTErrConvertFromErrno(errno);
     633                return rtProcPosixCreateReturn(VINF_SUCCESS, hEnvToUse, hEnv);
     634            }
     635            return rtProcPosixCreateReturn(RTErrConvertFromErrno(errno), hEnvToUse, hEnv);
    462636        }
    463637    }
     
    560734                if (phProcess)
    561735                    *phProcess = pid;
    562                 return VINF_SUCCESS;
     736                return rtProcPosixCreateReturn(VINF_SUCCESS, hEnvToUse, hEnv);
    563737            }
    564738        }
     
    577751            templateFd = rtSolarisContractPreFork();
    578752            if (templateFd == -1)
    579                 return VERR_OPEN_FAILED;
     753                return rtProcPosixCreateReturn(VERR_OPEN_FAILED, hEnvToUse, hEnv);
    580754        }
    581755#endif /* RT_OS_SOLARIS */
     
    627801            }
    628802#endif
     803
     804            /*
     805             * Some final profile environment tweaks, if running as user.
     806             */
     807            if (   (fFlags & RTPROC_FLAGS_PROFILE)
     808                && pszAsUser
     809                && (   (fFlags & RTPROC_FLAGS_ENV_CHANGE_RECORD)
     810                    || hEnv == RTENV_DEFAULT) )
     811            {
     812                rc = rtProcPosixAdjustProfileEnvFromChild(hEnvToUse, fFlags, hEnv);
     813                papszEnv = RTEnvGetExecEnvP(hEnvToUse);
     814                if (RT_FAILURE(rc) || !papszEnv)
     815                {
     816                    if (fFlags & RTPROC_FLAGS_DETACHED)
     817                        _Exit(126);
     818                    else
     819                        exit(126);
     820                }
     821            }
    629822
    630823            /*
     
    694887            if (phProcess)
    695888                *phProcess = pid;
    696             return VINF_SUCCESS;
     889            return rtProcPosixCreateReturn(VINF_SUCCESS, hEnvToUse, hEnv);
    697890        }
    698891        /* For a detached process this happens in the temp process, so
     
    700893        if (fFlags & RTPROC_FLAGS_DETACHED)
    701894            _Exit(124);
    702         return RTErrConvertFromErrno(errno);
    703     }
    704 
    705     return VERR_NOT_IMPLEMENTED;
     895        return rtProcPosixCreateReturn(RTErrConvertFromErrno(errno), hEnvToUse, hEnv);
     896    }
     897
     898    return rtProcPosixCreateReturn(VERR_NOT_IMPLEMENTED, hEnvToUse, hEnv);
    706899}
    707900
  • trunk/src/VBox/Runtime/testcase/tstRTProcCreateEx.cpp

    r57843 r57869  
    9090
    9191    int cErrors = 0;
    92     char szValue[_1K];
     92    char szValue[_16K];
    9393
    9494    /*
     
    166166    }
    167167
    168 #if 0
     168#if 1
    169169    /* For manual testing. */
    170170    if (strcmp(argv[2],"noinherit-change-record") == 0)
     
    178178            {
    179179                char szVarNm[_1K];
    180                 char szValue[_16K];
    181180                rc = RTEnvGetByIndexEx(hEnv, i, szVarNm, sizeof(szVarNm), szValue, sizeof(szValue));
    182181                if (RT_SUCCESS(rc))
     
    707706    if (pszAsUser)
    708707        tstRTCreateProcEx5(pszAsUser, pszPassword);
    709 #ifdef RT_OS_WINDOWS
    710708    tstRTCreateProcEx6(pszAsUser, pszPassword);
    711 #endif
    712709
    713710    /** @todo Cover files, ++ */
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette