11

I want to execute a terminal command of Linux in a C program. Currently I am using system() function but I want to use any other as the system() function is banned as per MISRA.

For example, how can I replace

system("hwclock --systohc --utc");
Benjamin Loison
  • 3,782
  • 4
  • 16
  • 33
BKT
  • 151
  • 2
  • 5
  • Are you sure that MISRA allows anything even *similar* to `system`? Executing arbitrary code is inherently unsafe. – molbdnilo Jun 05 '15 at 09:42
  • Actually when I tried for MISRA compliance of my code than it gives error that system() is a banned function. I am not sure whether MISRA allos anything similar to system. – BKT Jun 05 '15 at 11:10
  • If you **really** need to use a call to system() and you understand all the implications that go with that decision, raise a project deviation (see the early chapters of the book) and get your hierarchy to approve it. – Andrew Jun 20 '15 at 19:22
  • 1
    `execve()` should be legal. And the `posix_spawn` family of functions gives you plenty of higher-level equivalent choices -- the important thing with all of them is that you're invoking an explicit argv array, **not** a string that's parsed by a shell; too many people generate strings for shells to parse via simple concatenation and open themselves up to injection attacks. – Charles Duffy Jul 15 '21 at 23:11
  • @Andrew, ...I can't conceive of a valid reason to use `system()` -- not one. Even if you need a shell, you can still `posix_spawn()` `string[][]("sh", "-c", "...script here...", "sh", "first argument", "second argument")`, and thus pass your parameters out-of-band from your code (substituting parameters into code through string concatenation being the #1 way folks using `system()` shoot themselves and their users in the foot by creating shell injection vulnerabilities). – Charles Duffy Jul 15 '21 at 23:16
  • I would agree with you Charles, except `posix_spawn()` is not universally available. I would be interested in seeing a valid use case for a deviation to this Rule! – Andrew Jul 17 '21 at 08:03

5 Answers5

5

First you can use fork() to create a child process, then in the child process, you can call exec() to execute command what you want.
There is a simple example:

$ chmod u+x command.sh 
$ cat command.sh  
#!/usr/bin/env bash   
ls -l      

test.c:

#include<unistd.h>
int main(void)
{
  execl("./command.sh","command.sh",(char*)0);
  return 0;
}
Benjamin Loison
  • 3,782
  • 4
  • 16
  • 33
Ren
  • 2,852
  • 2
  • 23
  • 45
4

You can make use of fork() and then look up for exec() family of functions.

Alternatively, you may want to have a look at popen() also.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • `popen()` has the same security problems that cause `system()` to be banned. Any auditor who flags `system()` will object to `popen()` as well. – Charles Duffy Jul 15 '21 at 23:13
1

This is a very interesting question. My understanding of MISRA C is that it provides guidelines for the use of the C language in critical systems. But the C language standard library, which includes the system function, is merely a small piece of the sum total of library code typically used in modern applications -- often even in embedded systems.

I've never developed an application to MISRA standards, and I've only been able to find a slightly older (from 2004) version of the MISRA guidelines. From what I can tell, MISRA is silent about the use of POSIX library functions, which you are typically going to have available on any kind of Linux-based system. If MISRA really is silent about POSIX library functions, then it stands to reason that any functions in the POSIX library should be unrestricted. That would include fork, exec, and popen which are all defined by POSIX, not by the C language standard. Of the three, popen is probably most similar in functionality/interface to the C system function.

That said, you may want to ask yourself why MISRA C restricts the use of the system function and whether or not the same rationale applies to the use of the above three functions as well.

Dan Moulding
  • 211,373
  • 23
  • 97
  • 98
  • 2
    The rationale of MISRA is that `system()` contains too many forms of undefined and impl.defined behavior to be trusted. Also note that MISRA can be used outside mission-critical software, as a general coding standard, although it is biased towards embedded systems. MISRA doesn't care about POSIX since it is only concerned about standard C. Also, it is rare to use a POSIX OS for embedded systems, and even less so in mission-critical systems, for which you'd have to be quite insane to use some desktop OS like Linux or Windows. – Lundin Jun 08 '15 at 10:59
1

The letter of MISRA C:2012/2023 Rule 21.21 (previously part of MISRA C:2012 Rule 21.8) is that the system() function shall not be used.

The spirit of the Rule is that equivalent functions should not be used either - the rationale for the Rule explains why: executing external features is a major security vulnerability.

If you really need to do so, then the correct approach is deviate the Rule (with justification and mitigation) rather than trying to find a workaround.

-- See profile for affiliation.

Andrew
  • 2,046
  • 1
  • 24
  • 37
0

Using fork + exec family of functions is usually the suggested approach and a simple implementation is straightforward however what I've found is that it is a mine field of edge cases.

system() uses fork + exec internally and just look at glibc's implementation its source code is huge to deal with all the signal handlers. But signal handlers clearance + restoration must be dealt in a thread safe manner so there's also race condition issues that need to be accounted in multithreaded code, which is why glib's code is so unreadable.

I suggest you use posix_spawn instead if available, which is far more user friendly and, unlike system, has a safer interface.