Set a Bash function on the environment
Asked Answered
G

2

5

I need to define a Bash function in the Bash environment from a C/C++ program. Before the shellshock bug, I could define a function in this way:

my_func='() { echo "This is my function";}'

Or equivalent from a C program:

setenv("my_func", "() { echo \"This is my function\";}", 1);

Or

putenv("my_func=() { echo \"This is my function\";}");

But using a Bash version with shellshock fixed, I can't manage on how to define my functions in the environment.

The strange thing is, if I run env, I can see my function defined in the environment, but if I call it, Bash says that it doesn't exist.

Thanks in advance

Gorton answered 10/10, 2014 at 7:19 Comment(9)
Strange: someone who knows the internal and undocumented way exporting functions, doesn't know the documented way with the declare or export...Emalia
@jm666, already know about export -f, but I need to do it programatically from a C program. I don't know how to export a function definition from a C program to the environment without putenv or setenv. Thanks for your answerGorton
It is much better do such things in portable way, what can work e.g. in environments without bash, like plain-old-shell, dash, ksh, zsh and so on. Therefore, you probably want source them as @starrify already told you...Emalia
@jm666 I know, doing this won't be my choice, because it is very tricky, and the function is really long. But I was looking for a straight forward solution to the bug, due to the fact that we will refactor the Bash function to do it in a better way not very late in the future... I guess I will get the starrify advice and wrote the whole function in an external file and load from configuration file.Gorton
If you have a system which only works in the presence of the Shellshock bug, you should not update your Bash. Keep it at the old version, and sooner or later you will no longer have such a system. Problem solved.Burma
@JohnZwinck I'm not the system administrator, I'm currently trying to fix the problem of using the Shellshock bug. I was trying to find a way to define Bash functions in the environment from a C program. I don't take that kind of decisions. If I do, maybe the problematic function didn't exist for a long long time... Your comment is true and I agree with you, but is not helpful.Gorton
Perhaps you can tell us how you actually invoke Bash later in your program. Is it by calling system() or some other way?Burma
Use Older version of bash (without shellshock fix)Hemiplegia
@JohnZwinck it is invoked using execv, without any fork... I don't like anything about this solution, but I'm only resolving a bug, the managers won't booked time of my work for resolving the entire piece of software :-(Gorton
Q
2

If you are invoking bash with execv (so that you are only invoking it once), you could replace (using execl for explanatory purposes):

 execl("/bin/bash", "bash", "file_to_run", "arg1", "arg2", 0);

with

 execl("/bin/bash", "bash", "-c", "f() {...} g() {...}\n. $0",
                    "file_to_run", "arg1", "arg2", 0);

and then you don't need to play games with the internal bash interface for defining functions. (If the bash script being run also needs the functions to be exported, for whatever reason, just add export -f <func> lines to the argument following -c.)

That has the advantage of working with both patched and unpatched bashes.

(I'm having to make a similar patch to various programs, so I share your pain.)

Quaternion answered 10/10, 2014 at 16:11 Comment(0)
R
8

For informational purposes only. Since it is not documented how functions are exported to the environment, you should treat this as an abuse of a private API that is subject to change in future versions of bash.

Functions are no longer exported using simply the name of the function in the environment string. To see this, run

$ my_func () { echo "foo"; }
$ export -f my_func
$ env | grep -A1 'my_func'
BASH_FUNC_my_func%%=() {  echo "foo"
}

Since the name used in the environment is no longer a valid bash identifier, you would need to use the env command to modify the environment of the new process.

env 'BASH_FUNC_my_func%%=() { echo "This is my function"; }' bash

From C, you just need to adjust the name.​​​​​​

setenv("BASH_FUNC_my_func%%", "() { echo \"This is my function\";}", 1);
Rattish answered 10/10, 2014 at 13:20 Comment(2)
May be relevant: Bash Code Injection Vulnerability via Specially Crafted Environment VariablesApodosis
From a Java programa, I cannot set a function definition using the provided syntax. With env it does work.Boeschen
Q
2

If you are invoking bash with execv (so that you are only invoking it once), you could replace (using execl for explanatory purposes):

 execl("/bin/bash", "bash", "file_to_run", "arg1", "arg2", 0);

with

 execl("/bin/bash", "bash", "-c", "f() {...} g() {...}\n. $0",
                    "file_to_run", "arg1", "arg2", 0);

and then you don't need to play games with the internal bash interface for defining functions. (If the bash script being run also needs the functions to be exported, for whatever reason, just add export -f <func> lines to the argument following -c.)

That has the advantage of working with both patched and unpatched bashes.

(I'm having to make a similar patch to various programs, so I share your pain.)

Quaternion answered 10/10, 2014 at 16:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.