Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 520ca3e1 authored by Nick Kralevich's avatar Nick Kralevich Committed by Gerrit Code Review
Browse files

Merge "builtins.c: Don't require file open() for chmod/chown"

parents 88342c99 bc60954f
Loading
Loading
Loading
Loading
+8 −63
Original line number Diff line number Diff line
@@ -49,6 +49,8 @@

#include <private/android_filesystem_config.h>

#define chmod DO_NOT_USE_CHMOD_USE_FCHMODAT_SYMLINK_NOFOLLOW

int add_environment(const char *name, const char *value);

extern int init_module(void *, unsigned long, const char *);
@@ -76,63 +78,6 @@ static int write_file(const char *path, const char *value)
    }
}

static int _open(const char *path)
{
    int fd;

    fd = open(path, O_RDONLY | O_NOFOLLOW);
    if (fd < 0)
        fd = open(path, O_WRONLY | O_NOFOLLOW);

    return fd;
}

static int _chown(const char *path, unsigned int uid, unsigned int gid)
{
    int fd;
    int ret;

    fd = _open(path);
    if (fd < 0) {
        return -1;
    }

    ret = fchown(fd, uid, gid);
    if (ret < 0) {
        int errno_copy = errno;
        close(fd);
        errno = errno_copy;
        return -1;
    }

    close(fd);

    return 0;
}

static int _chmod(const char *path, mode_t mode)
{
    int fd;
    int ret;

    fd = _open(path);
    if (fd < 0) {
        return -1;
    }

    ret = fchmod(fd, mode);
    if (ret < 0) {
        int errno_copy = errno;
        close(fd);
        errno = errno_copy;
        return -1;
    }

    close(fd);

    return 0;
}

static int insmod(const char *filename, char *options)
{
    void *module;
@@ -320,7 +265,7 @@ int do_mkdir(int nargs, char **args)
    ret = make_dir(args[1], mode);
    /* chmod in case the directory already exists */
    if (ret == -1 && errno == EEXIST) {
        ret = _chmod(args[1], mode);
        ret = fchmodat(AT_FDCWD, args[1], mode, AT_SYMLINK_NOFOLLOW);
    }
    if (ret == -1) {
        return -errno;
@@ -334,13 +279,13 @@ int do_mkdir(int nargs, char **args)
            gid = decode_uid(args[4]);
        }

        if (_chown(args[1], uid, gid) < 0) {
        if (lchown(args[1], uid, gid) == -1) {
            return -errno;
        }

        /* chown may have cleared S_ISUID and S_ISGID, chmod again */
        if (mode & (S_ISUID | S_ISGID)) {
            ret = _chmod(args[1], mode);
            ret = fchmodat(AT_FDCWD, args[1], mode, AT_SYMLINK_NOFOLLOW);
            if (ret == -1) {
                return -errno;
            }
@@ -814,10 +759,10 @@ out:
int do_chown(int nargs, char **args) {
    /* GID is optional. */
    if (nargs == 3) {
        if (_chown(args[2], decode_uid(args[1]), -1) < 0)
        if (lchown(args[2], decode_uid(args[1]), -1) == -1)
            return -errno;
    } else if (nargs == 4) {
        if (_chown(args[3], decode_uid(args[1]), decode_uid(args[2])) < 0)
        if (lchown(args[3], decode_uid(args[1]), decode_uid(args[2])) == -1)
            return -errno;
    } else {
        return -1;
@@ -840,7 +785,7 @@ static mode_t get_mode(const char *s) {

int do_chmod(int nargs, char **args) {
    mode_t mode = get_mode(args[1]);
    if (_chmod(args[2], mode) < 0) {
    if (fchmodat(AT_FDCWD, args[2], mode, AT_SYMLINK_NOFOLLOW) < 0) {
        return -errno;
    }
    return 0;