Search code examples
cglib

Running cat /proc/cpuinfo in glib


I've been trying to look for questions on how to use g_spawn_sync() and they said that it is good to use when you want to execute a command in the terminal besides using pipes.

The only thing I can't figure out now is why the command cat /proc/cpuinfo doesn't work. error->message returns (No such file or directory)but if I use commands like ls or cat alone, it works. I also tried running cd /proc && cat cpuinfo but it gives me the same error.

I'm not an expert of glib but I read in the manual that I can use G_SPAWN_SEARCH_PATH so that it will check my PATH for the commands I can use without including the absolute path for the command.

I have the following code:

gchar *argv[] = { "cat /proc/cpuinfo", NULL };
char *output = NULL; // will contain command output
GError *error = NULL;
int exit_status = 0;
if (!g_spawn_sync(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, 
                &output, NULL, &exit_status, &error))
{
    printf("[getHardwareInfo] DEBUG: Error on g_spawn_sync %s.\n", error->message);

}

Solution

  • tl;dr: Do not use g_spawn_command_line_sync() unless you really know what you are doing.

    Firstly, the actual problem you are hitting: John Szakmeister’s comment was correct: g_spawn_sync() takes an array of arguments, the first one of which is the path to the program to execute (or to look for in $PATH, if you’ve specified G_SPAWN_SEARCH_PATH). By passing the array { "cat /proc/cpuinfo", NULL }, you are saying that you want to run the program cat /proc/cpuinfo with no arguments, not the program cat with the argument /proc/cpuinfo.

    However, there are many other problems here, and I think it’s important to mention them before people start cargo-culting this code, because they have security implications:

    • As LegalProgrammer says, why are you spawning cat when you could just call g_file_get_contents()?
    • Failing that, use GSubprocess instead of g_spawn_*(). It’s a more modern API, which allows you to monitor the lifecycle of the spawned process more easily, as well as getting streaming I/O in and out of the subprocess.
    • Do not ignore the warnings in the manual about the security implications of using g_spawn_command_line_sync(). There are several:
      • It will run the first matching program found in your $PATH, so if an attacker has control of your $PATH, or write access to any directory in that $PATH (such as ~/.local/bin), you will end up running an attacker-controlled program.
      • It’s a synchronous function, so will block on the subprocess completing, which could take unbounded time. Your program will be unresponsive for that time.
      • It returns the output in a single allocation, rather than as a stream, so if the subprocess returns many megabytes of output, you may hit allocation failures and abort.
      • The obvious next step from “g_spawn_command_line_sync() seems to do what I want” is “let’s use g_strdup_printf() to put together a command to run with it”, and then you have shell injection vulnerabilities, where an attacker who controls any of the parameters to that printf() can twist the entire shell command to execute their arbitrary code.