From 6d974bb4cb6b0d8732c46d6372a7759296327110 Mon Sep 17 00:00:00 2001 From: Sangyoon Jang Date: Wed, 8 Jun 2016 16:14:21 +0900 Subject: [PATCH] Prevent race condition attack Use fchown, fchmod instead of chown, chmod. Change-Id: I8b2e0a5a2a4df5171d67df46faff5d7841015487 Signed-off-by: Sangyoon Jang --- parser/pkgmgr_parser_db.c | 34 ++++++++++++++++++++++++++++++---- src/pkgmgrinfo_db.c | 31 ++++++++++++++++++++++++++++--- 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/parser/pkgmgr_parser_db.c b/parser/pkgmgr_parser_db.c index 974a18b..385d09b 100644 --- a/parser/pkgmgr_parser_db.c +++ b/parser/pkgmgr_parser_db.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -2553,6 +2554,8 @@ static int __parserdb_change_perm(const char *db_file, uid_t uid) char buf[BUFSIZE]; char pwuid_buf[1024]; char journal_file[BUFSIZE]; + int fd; + struct stat sb; char *files[3]; int ret, i; struct passwd userinfo, *result = NULL; @@ -2577,25 +2580,48 @@ static int __parserdb_change_perm(const char *db_file, uid_t uid) snprintf(journal_file, sizeof(journal_file), "%s%s", db_file, "-journal"); for (i = 0; files[i]; i++) { - ret = chown(files[i], uid, userinfo.pw_gid); + fd = open(files[i], O_RDONLY); + if (fd == -1) { + if (strerror_r(errno, buf, sizeof(buf))) + strncpy(buf, "", BUFSIZE - 1); + _LOGD("FAIL : open %s : %s", files[i], buf); + return -1; + } + ret = fstat(fd, &sb); + if (ret == -1) { + if (strerror_r(errno, buf, sizeof(buf))) + strncpy(buf, "", BUFSIZE - 1); + _LOGD("FAIL : fstat %s : %s", files[i], buf); + close(fd); + return -1; + } + if (S_ISLNK(sb.st_mode)) { + _LOGE("FAIL : %s is symlink!", files[i]); + close(fd); + return -1; + } + ret = fchown(fd, uid, userinfo.pw_gid); if (ret == -1) { if (strerror_r(errno, buf, sizeof(buf))) strncpy(buf, "", BUFSIZE - 1); - _LOGD("FAIL : chown %s %d.%d : %s", files[i], uid, + _LOGD("FAIL : fchown %s %d.%d : %s", files[i], uid, userinfo.pw_gid, buf); + close(fd); return -1; } mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH; if (!strcmp(db_file, getUserPkgCertDBPathUID(GLOBAL_USER))) mode |= S_IWOTH; - ret = chmod(files[i], mode); + ret = fchmod(fd, mode); if (ret == -1) { if (strerror_r(errno, buf, sizeof(buf))) strncpy(buf, "", BUFSIZE - 1); - _LOGD("FAIL : chmod %s 0664 : %s", files[i], buf); + _LOGD("FAIL : fchmod %s 0664 : %s", files[i], buf); + close(fd); return -1; } + close(fd); SET_SMACK_LABEL(files[i]); } return 0; diff --git a/src/pkgmgrinfo_db.c b/src/pkgmgrinfo_db.c index 50eac61..3aca7de 100644 --- a/src/pkgmgrinfo_db.c +++ b/src/pkgmgrinfo_db.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -86,6 +87,8 @@ static int _mkdir_for_user(const char* dir, uid_t uid, gid_t gid) char *fullpath; char *subpath; char buf[1024]; + int fd; + struct stat sb; fullpath = strdup(dir); if (fullpath == NULL) @@ -109,10 +112,32 @@ static int _mkdir_for_user(const char* dir, uid_t uid, gid_t gid) } if (getuid() == ROOT_UID) { - ret = chown(dir, uid, gid); - if (ret == -1) - _LOGE("FAIL : chown %s %d.%d, because %s", dir, uid, + fd = open(dir, O_RDONLY); + if (fd == -1) { + _LOGE("FAIL : open %s : %s", dir, + strerror_r(errno, buf, sizeof(buf))); + return -1; + } + ret = fstat(fd, &sb); + if (ret == -1) { + _LOGE("FAIL : fstat %s : %s", dir, + strerror_r(errno, buf, sizeof(buf))); + close(fd); + return -1; + } + if (S_ISLNK(sb.st_mode)) { + _LOGE("FAIL : %s is symlink!", dir); + close(fd); + return -1; + } + ret = fchown(fd, uid, gid); + if (ret == -1) { + _LOGE("FAIL : fchown %s %d.%d, because %s", dir, uid, gid, strerror_r(errno, buf, sizeof(buf))); + close(fd); + return -1; + } + close(fd); } free(fullpath); -- 2.7.4