Question

I am trying to make a few fixes and enhancements to Jailkit. The source is in CVS version control so I cloned it to GitHub.

The way this is set up, you edit a user's home directory in /etc/passwd to be something like:

/home/jail/./home/username

Then the getjaildir function reads over that which is passed in as oldhomedir until it finds the first /./ match right to left on the string and then will set jaildir to what is to the left of that and the newhomedir to everything to the right of that.

I want to be able to override jaildir with the value from a configuration file - but I suck at c and so I am having very difficult time even setting the variables manually.

Here is the function:

/* if it returns 1 it will allocate new memory for jaildir and newhomedir
 * else it will return 0
 */
int getjaildir(const char *oldhomedir, char **jaildir, char **newhomedir) {
    int i=strlen(oldhomedir);
    /* we will not accept /./ as jail, so we continue looking while i > 4 (minimum then is /a/./ )
     * we start at the end so if there are multiple /path/./path2/./path3 the user will be jailed in the most minimized path
     */
    while (i > 4) {
/*      DEBUG_MSG("oldhomedir[%d]=%c\n",i,oldhomedir[i]);*/
        if (oldhomedir[i] == '/' && oldhomedir[i-1] == '.' && oldhomedir[i-2] == '/') {
            DEBUG_MSG("&oldhomedir[%d]=%s\n",i,&oldhomedir[i]);
            *jaildir = strndup(oldhomedir, i-2);
            *newhomedir = strdup(&oldhomedir[i]);
            return 1;
        }
        i--;
    }
    return 1;
}

After many, many attempts at a more complex solution I tried a very simple, hard-coded variation:

int getjaildir(const char *oldhomedir, char **jaildir, char **newhomedir) {
    *jaildir = "/home/jail";
    *newhomedir = "/home/username";
    return 1;
}

This compiles fine on linux but when I run it I end up getting Segmentation fault (11). I read up on pointers, addresses, dereferencing, variable types, string concatenation, etc. but unfortunately I'm used to loosely typed languages so this is pretty hard. What am I doing wrong?

update

Instead of setting the values in the getjaildir function I am attempting to set them in the mail loop.

At the top of the loop we have the variable definitions:

    char *jaildir=NULL, *newhome=NULL, *shell=NULL;

And here is where the function to set them is called:

if (!getjaildir(pw->pw_dir, &jaildir, &newhome)) {
        syslog(LOG_ERR, "abort, failed to read the jail and the home from %s for user %s (%d)",pw->pw_dir, pw->pw_name, getuid());
        exit(17);
}

Can I just do this immediately afterwards to overwrite the values?

jaildir="/home/jail";
newhome="/home/testuser";

When I try this it gives me:

*** glibc detected *** -su: munmap_chunk(): invalid pointer: 0x00000000004046ee ***
Was it helpful?

Solution

How do you call getjaildir?

When I tried it, it works, as it should.

int getjaildir(const char *oldhomedir, char **jaildir, char **newhomedir)
{
    *jaildir = "/home/jail";
    *newhomedir = "/home/username";
    return 1;
}

int main(int argc, char *argv[])
{
    char *ohome = "ohome";
    char *nhome = "nhome";
    char *jdir = "jdir";
    getjaildir(ohome, &jdir, &nhome);

    printf("%s:%s:%s\n", ohome, jdir, nhome);
}

Output:

ohome:/home/jail:/home/username

update

I looked at oyur link and now I think I know what the problem is. You are retrieving the password stucture with a call to gepwnam. However this function returns a static memory, which you should NOT overwerwrite. So either you have to copy the strcuture manually, before you start modifying it, or you provide your own memory to it. For details on how to this you can refer to http://linux.die.net/man/3/getpwnam and look at getpwnam_r. Basically you allocate this memory beforehand and pass it to the function. You must make sure that enough memory is allocated as all the entries are put into this buffer you provided. When you change your code accordingly it shouldn't crash.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top