28 Oct 2007

Is there a safer way to use system()?

Many security guidelines tell people not to use system() and similar functions, because the command is passed wholesale to the shell, and if the shell string isn't escaped properly, then you have all sorts of security problems: attackers can insert redirections to files (and file descriptors) they wouldn't otherwise have access to, and insert arbitrary commands by using ;, &, &&, ||, backticks, etc.

Yet, at the same time, system() is convenient: you don't have to build up your argument array by hand, you don't have to perform token parsing, variable substitution, or tilde expansion, and you don't have to do all the forking work. So, really, you just want all the conveniences of system() without the security risks.

Well, here's something that just might do the job, in certain instances where allowing users to specify command-line arguments is useful. Rather than passing the string to the shell, it uses wordexp() to do the parsing/substitution/expansion, which rejects all the unescaped shell metacharacters and backtick usages. I need to do more testing to be sure, but I am of the opinion that it's somewhat safer to use than system().

My code is based on the implementation of system() provided in the Single Unix Specification, and I release my modifications into the public domain.


#include <sys/wait.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <wordexp.h>

int
safer_system(const char *command)
{
    int result;
    struct sigaction sa_new, sa_oldintr, sa_oldquit;
    sigset_t ss_newblock, ss_oldblock;
    pid_t pid;
    wordexp_t we = {};

    if (!command)
        return 1;

    sa_new.sa_handler = SIG_IGN;
    sigemptyset(&sa_new.sa_mask);
    sa_new.sa_flags = 0;
    sigaction(SIGINT, &sa_new, &sa_oldintr);
    sigaction(SIGQUIT, &sa_new, &sa_oldquit);

    sigemptyset(&ss_newblock);
    sigaddset(&ss_newblock, SIGCHLD);
    sigprocmask(SIG_BLOCK, &ss_newblock, &ss_oldblock);

    switch (pid = fork()) {
    case -1:
        result = -1;
        break;

    case 0:
        sigaction(SIGINT, &sa_oldintr, NULL);
        sigaction(SIGQUIT, &sa_oldquit, NULL);
        sigprocmask(SIG_SETMASK, &ss_oldblock, NULL);
        if (wordexp(command, &we, WRDE_NOCMD)) {
            errno = EINVAL;
            return -1;
        }
        execvp(*we.we_wordv, we.we_wordv);
        _exit(127);
        /* NOTREACHED */

    default:
        while (waitpid(pid, &result, 0) == -1) {
            if (errno != EINTR) {
                result = -1;
                break;
            }
        }
    }

    sigaction(SIGINT, &sa_oldintr, NULL);
    sigaction(SIGQUIT, &sa_oldquit, NULL);
    sigprocmask(SIG_SETMASK, &ss_oldblock, NULL);
    return result;
}

My original version did the wordexp() call in the parent process, but this then expands $$ to the wrong process ID. There may be other bugs in this approach that I have yet to discover; as mentioned, I haven't done very much testing with it yet.

On quality relationships, part 1

Many thanks to my friend Nathan whose Final nail article inspired this one.

I totally identify with Nathan's article, because it really upsets me when people try to do too much on a first date. I have had similar experiences (which I won't go into specifics about, both out of respect for those involved, and to protect my privacy and theirs), and I, too, chose to back off.

I chose to back off because I feel that when someone tries to be physical with me before knowing me personally and emotionally, before we establish a meaningful relationship, I worry about the possibility that emotional compatibility is less important to them than physical compatibility. This is doubly so because I'm an introvert (so I actively hide my real self), and thus it takes a lot of effort to know who I am, something that many people I know have difficulty fully understanding. I am a very different person in my own space, much harder to get along with than the social personae (yes, plural) that people usually know me by.

Now, I'm not saying that physical compatibility is not important: sex and physical affection are vital components of a good relationship, but I feel that it cannot be built primarily upon physical aspects. Honest, open communication, which I think too many couples have trouble dealing with, is much more critical (pun intended), for without it, a long-lasting relationship is almost impossible. We each are all too different to begin with; without a solid way to bridge these gaps, what hope have we got?

That's not to say that I'm perfect at communicating. Far, far from it; I still have difficulty dealing with blunt truth, and I dare say I still verbally tiptoe around my spouse too much for my liking. But I do commit to putting in the hard work needed to improve on it, and it is the top priority in my marriage.

Imagine, if you were to share your body, your intimate space, and your heart, with somebody whom, yes, you do share a strong attraction with, but whom you also know you cannot have a long-lasting and meaningful relationship with, because something much more important is in the way, like being unable to talk openly with each other. I can't speak for you, but that'd break my heart more than I want to think about.

18 Aug 2007

On open relationships

A friend asked a very interesting question on My Questions: Is there a premise for open relationships?

Most of you who know me (for some value of know) probably realise that I openly (pun intended) favour open relationships. But, your mileage may vary, and it has a lot to do with what a relationship means to you, and more importantly, what an open relationship means to you.

In the broadest sense, an open relationship is one where its parties can negotiate any terms they can all agree to. However, I would like to narrow the case to the one used in my marriage, because it forms the ‘premise’ which I will use to answer the question.

To me, an open relationship is one where you can establish additional relationships, with the free consent of your existing partner(s). By free consent, I mean that any reservations your partner(s) have about the new relationship, including jealousy and trust issues, have to be resolved before it begins. This way, relationships are only made when everyone wants it, and there is no resentment or bitterness involved.

For this to be effective, we have an agreement in place to allow an existing partner to veto a potential relationship without reprisal (emotional or otherwise). Without this, it'd allow you to pressure your partner to let you start a new relationship against their wishes, and that's not on.

Obviously, everyone involved must have a very established and very honest communication style, so that any issues that arise from the new relationship can be sensibly dealt with, and not be left sitting to develop into destructive resentment. (We have an agreement to openly express our feelings about anything that concerns us, and not to hide anything. Despite this, I am not good at being direct, nor at listening to direct comments, so I have a lot to work on before we're ready to take on new partners.)

Now, I can hear some of you ask, what about the sex? For both of us (being the INFPs that we both are), sex is all about the emotional connection, much more than about the physical satisfaction or whatever else people get out of it. I cannot imagine either of us wanting to have sex with anyone we're not in a relationship with. Your mileage may vary, and if so, then a frank discussion of what kind of sex is acceptable with whom is an absolute necessity.

So then, onto the premise. I think with the right rules and boundaries, and with the right relationship, there are a lot of emotional benefits to running an open relationship. You get to explore relationships with other people in ways that most monogamous people never get to do (without cheating)—and I do believe that some people can add (emotional or other) value to a strong relationship, even if only because we're all unique and by learning more about others, we learn more about ourselves. Also, you never have to worry about a partner being jealous, or wonder just how far you can go before things cease to be okay—these are all discussed beforehand.

But—as I just mentioned, an open relationship can only grow from a place of strength—it cannot be used as a crutch for anything. If an existing relationship has signs of trouble, trying to start an open relationship is likely to be disastrous (much like trying to start a family from a troubled relationship). You have to have the confidence that your relationship will carry the new relationship and all the dramas that come with it. Without it, you'll always worry about whether the relationship will work, and this worry will eat the relationship alive.

And though it's my third time saying it, your mileage may vary.