Ejemplo n.º 1
0
//--------------------------------------------------------------------------------------------------
void supCtrl_GetLabel
(
    const char* appName,  ///< [IN]  Application name.
    char* label,          ///< [OUT] SMACK label for the application.
    size_t labelSize      ///< [IN]  Size of the SMACK label string.
)
//--------------------------------------------------------------------------------------------------
{
    static bool connectedToSmack = false;

    if (!connectedToSmack)
    {
        appSmack_ConnectService();
        connectedToSmack = true;
    }

    appSmack_GetLabel(appName, label, labelSize);
}
Ejemplo n.º 2
0
//--------------------------------------------------------------------------------------------------
static inline le_result_t StartProc
(
    proc_Ref_t procRef,             ///< [IN] The process to start.
    const char* workingDirPtr,      ///< [IN] The path to the process's working directory, relative
                                    ///       to the sandbox directory.
    uid_t uid,                      ///< [IN] The user ID to start the process as.
    gid_t gid,                      ///< [IN] The primary group ID for this process.
    const gid_t* groupsPtr,         ///< [IN] List of supplementary groups for this process.
    size_t numGroups,               ///< [IN] The number of groups in the supplementary groups list.
    const char* sandboxDirPtr       ///< [IN] The path to the root of the sandbox this process is to
                                    ///       run in.  If NULL then process will be unsandboxed.
)
{
    if (procRef->pid != -1)
    {
        LE_ERROR("Process '%s' (PID: %d) cannot be started because it is already running.",
                 procRef->name, procRef->pid);
        return LE_FAULT;
    }

    // Create a pipe for parent/child synchronization.
    int syncPipeFd[2];
    LE_FATAL_IF(pipe(syncPipeFd) == -1, "Could not create synchronization pipe.  %m.");

    // @Note The current IPC system does not support forking so any reads to the config DB must be
    //       done in the parent process.

    // Get the environment variables from the config tree for this process.
    EnvVar_t envVars[LIMIT_MAX_NUM_ENV_VARS];
    int numEnvVars = GetEnvironmentVariables(procRef, envVars, LIMIT_MAX_NUM_ENV_VARS);

    if (numEnvVars == LE_FAULT)
    {
        LE_ERROR("Error getting environment variables.  Process '%s' cannot be started.",
                 procRef->name);
        return LE_FAULT;
    }

    // Get the command line arguments from the config tree for this process.
    char argsBuffers[LIMIT_MAX_NUM_CMD_LINE_ARGS][LIMIT_MAX_ARGS_STR_BYTES];
    char* argsPtr[NUM_ARGS_PTRS];

    if (GetArgs(procRef, argsBuffers, argsPtr) != LE_OK)
    {
        LE_ERROR("Could not get command line arguments, process '%s' cannot be started.",
                 procRef->name);
        return LE_FAULT;
    }

    // Get the smack label for the process.
    // Must get the label here because smack_GetAppLabel uses the config and we can not
    // use any IPC after a fork.
    char smackLabel[LIMIT_MAX_SMACK_LABEL_BYTES];
    appSmack_GetLabel(app_GetName(procRef->appRef), smackLabel, sizeof(smackLabel));

    // Create pipes for the process's standard error and standard out streams.
    int stderrPipe[2];
    int stdoutPipe[2];
    CreatePipe(procRef, stderrPipe, STDERR_FILENO);
    CreatePipe(procRef, stdoutPipe, STDOUT_FILENO);

    // Create the child process
    pid_t pID = fork();

    if (pID < 0)
    {
        LE_EMERG("Failed to fork.  %m.");
        return LE_FAULT;
    }

    if (pID == 0)
    {
        // Wait for the parent to allow us to continue by blocking on the read pipe until it
        // is closed.
        fd_Close(syncPipeFd[WRITE_PIPE]);

        ssize_t numBytesRead;
        int dummyBuf;
        do
        {
            numBytesRead = read(syncPipeFd[READ_PIPE], &dummyBuf, 1);
        }
        while ( ((numBytesRead == -1)  && (errno == EINTR)) || (numBytesRead != 0) );

        LE_FATAL_IF(numBytesRead == -1, "Could not read synchronization pipe.  %m.");

        // The parent has allowed us to continue.

        // Redirect the process's standard streams.
        RedirectStdStream(stderrPipe, STDERR_FILENO);
        RedirectStdStream(stdoutPipe, STDOUT_FILENO);

        // Set the process's SMACK label.
        smack_SetMyLabel(smackLabel);

        // Set the umask so that files are not accidentally created with global permissions.
        umask(S_IRWXG | S_IRWXO);

        // Unblock all signals that might have been blocked.
        sigset_t sigSet;
        LE_ASSERT(sigfillset(&sigSet) == 0);
        LE_ASSERT(pthread_sigmask(SIG_UNBLOCK, &sigSet, NULL) == 0);

        SetEnvironmentVariables(envVars, numEnvVars);

        // Setup the process environment.
        if (sandboxDirPtr != NULL)
        {
            // Sandbox the process.
            sandbox_ConfineProc(sandboxDirPtr, uid, gid, groupsPtr, numGroups, workingDirPtr);
        }
        else
        {
            ConfigNonSandboxedProcess(workingDirPtr);
        }

        // Launch the child program.  This should not return unless there was an error.
        LE_INFO("Execing '%s'", argsPtr[0]);

        // Close all non-standard file descriptors.
        fd_CloseAllNonStd();

        execvp(argsPtr[0], &(argsPtr[1]));

        // The program could not be started.  Log an error message.
        log_ReInit();
        LE_FATAL("Could not exec '%s'.  %m.", argsPtr[0]);
    }

    procRef->pid = pID;
    procRef->paused = false;

    // Don't need this end of the pipe.
    fd_Close(syncPipeFd[READ_PIPE]);

    // Set the scheduling priority for the child process while the child process is blocked.
    SetSchedulingPriority(procRef);

    // Send standard pipes to the log daemon so they will show up in the logs.
    SendStdPipeToLogDaemon(procRef, stderrPipe, STDERR_FILENO);
    SendStdPipeToLogDaemon(procRef, stdoutPipe, STDOUT_FILENO);

    // Set the resource limits for the child process while the child process is blocked.
    if (resLim_SetProcLimits(procRef) != LE_OK)
    {
        LE_ERROR("Could not set the resource limits.  %m.");

        kill_Hard(procRef->pid);
    }

    LE_INFO("Starting process %s with pid %d", procRef->name, procRef->pid);

    // Unblock the child process.
    fd_Close(syncPipeFd[WRITE_PIPE]);

    return LE_OK;
}