summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiang Cheng <licheng@nvidia.com>2014-01-02 18:27:51 -0800
committerNick Kralevich <nnk@google.com>2014-01-02 20:26:18 -0800
commit20d33f4d99c26afdd0aebf23786958ef34e261e3 (patch)
treed24de4259e3e2fe5ef37372c7de54b7173d67ccd
parentdfc48139c9afc8366184a1a7bc2f3762c0c82ea2 (diff)
downloadsystem_core-20d33f4d99c26afdd0aebf23786958ef34e261e3.zip
system_core-20d33f4d99c26afdd0aebf23786958ef34e261e3.tar.gz
system_core-20d33f4d99c26afdd0aebf23786958ef34e261e3.tar.bz2
adb: configure /system file permission with fs_config
adbd changes the permissions of files uploaded by copying owner's permission to group and other. This causes kernel load failure if any changes are made to kernel modules followed by ``adb push'' or ``adb sync'' because file mode 644 would become 666. The change uses fs_config to get the target mode of files. In addition, the SELinux file label is set incorrectly on synced files. Set the label properly. Change-Id: I354db848f39adfbf189d7e8d3b028e8d763c772f Signed-off-by: Liang Cheng <licheng@nvidia.com> Bug: 12264775
-rw-r--r--adb/Android.mk2
-rw-r--r--adb/file_sync_service.c73
2 files changed, 65 insertions, 10 deletions
diff --git a/adb/Android.mk b/adb/Android.mk
index 721b48d..155c6e5 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -130,7 +130,7 @@ LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)
LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)
-LOCAL_STATIC_LIBRARIES := liblog libcutils libc libmincrypt
+LOCAL_STATIC_LIBRARIES := liblog libcutils libc libmincrypt libselinux
include $(BUILD_EXECUTABLE)
diff --git a/adb/file_sync_service.c b/adb/file_sync_service.c
index f24f14c..c30f9fb 100644
--- a/adb/file_sync_service.c
+++ b/adb/file_sync_service.c
@@ -22,19 +22,32 @@
#include <sys/types.h>
#include <dirent.h>
#include <utime.h>
+#include <unistd.h>
#include <errno.h>
-
+#include <private/android_filesystem_config.h>
+#include <selinux/android.h>
#include "sysdeps.h"
#define TRACE_TAG TRACE_SYNC
#include "adb.h"
#include "file_sync_service.h"
+/* TODO: use fs_config to configure permissions on /data */
+static bool is_on_system(const char *name) {
+ const char *SYSTEM = "/system/";
+ return (strncmp(SYSTEM, name, strlen(SYSTEM)) == 0);
+}
+
static int mkdirs(char *name)
{
int ret;
char *x = name + 1;
+ unsigned int uid, gid;
+ unsigned int mode = 0775;
+ uint64_t cap = 0;
+ uid = getuid();
+ gid = getgid();
if(name[0] != '/') return -1;
@@ -42,11 +55,21 @@ static int mkdirs(char *name)
x = adb_dirstart(x);
if(x == 0) return 0;
*x = 0;
- ret = adb_mkdir(name, 0775);
+ if (is_on_system(name)) {
+ fs_config(name, 1, &uid, &gid, &mode, &cap);
+ }
+ ret = adb_mkdir(name, mode);
if((ret < 0) && (errno != EEXIST)) {
D("mkdir(\"%s\") -> %s\n", name, strerror(errno));
*x = '/';
return ret;
+ } else if(ret == 0) {
+ ret = chown(name, uid, gid);
+ if (ret < 0) {
+ *x = '/';
+ return ret;
+ }
+ selinux_android_restorecon(name);
}
*x++ = '/';
}
@@ -149,7 +172,8 @@ static int fail_errno(int s)
return fail_message(s, strerror(errno));
}
-static int handle_send_file(int s, char *path, mode_t mode, char *buffer)
+static int handle_send_file(int s, char *path, unsigned int uid,
+ unsigned int gid, mode_t mode, char *buffer)
{
syncmsg msg;
unsigned int timestamp = 0;
@@ -157,8 +181,13 @@ static int handle_send_file(int s, char *path, mode_t mode, char *buffer)
fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode);
if(fd < 0 && errno == ENOENT) {
- mkdirs(path);
- fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode);
+ if(mkdirs(path) != 0) {
+ if(fail_errno(s))
+ return -1;
+ fd = -1;
+ } else {
+ fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode);
+ }
}
if(fd < 0 && errno == EEXIST) {
fd = adb_open_mode(path, O_WRONLY, mode);
@@ -167,6 +196,16 @@ static int handle_send_file(int s, char *path, mode_t mode, char *buffer)
if(fail_errno(s))
return -1;
fd = -1;
+ } else {
+ if(fchown(fd, uid, gid) != 0) {
+ fail_errno(s);
+ errno = 0;
+ }
+ /* fchown clears the setuid bit - restore it if present */
+ if(fchmod(fd, mode) != 0) {
+ fail_errno(s);
+ errno = 0;
+ }
}
for(;;) {
@@ -206,6 +245,7 @@ static int handle_send_file(int s, char *path, mode_t mode, char *buffer)
if(fd >= 0) {
struct utimbuf u;
adb_close(fd);
+ selinux_android_restorecon(path);
u.actime = timestamp;
u.modtime = timestamp;
utime(path, &u);
@@ -249,7 +289,10 @@ static int handle_send_link(int s, char *path, char *buffer)
ret = symlink(buffer, path);
if(ret && errno == ENOENT) {
- mkdirs(path);
+ if(mkdirs(path) != 0) {
+ fail_errno(s);
+ return -1;
+ }
ret = symlink(buffer, path);
}
if(ret) {
@@ -277,7 +320,7 @@ static int handle_send_link(int s, char *path, char *buffer)
static int do_send(int s, char *path, char *buffer)
{
char *tmp;
- mode_t mode;
+ unsigned int mode;
int is_link, ret;
tmp = strrchr(path,',');
@@ -288,7 +331,7 @@ static int do_send(int s, char *path, char *buffer)
#ifndef HAVE_SYMLINKS
is_link = 0;
#else
- is_link = S_ISLNK(mode);
+ is_link = S_ISLNK((mode_t) mode);
#endif
mode &= 0777;
}
@@ -307,11 +350,23 @@ static int do_send(int s, char *path, char *buffer)
#else
{
#endif
+ unsigned int uid, gid;
+ uint64_t cap = 0;
+ uid = getuid();
+ gid = getgid();
+
/* copy user permission bits to "group" and "other" permissions */
mode |= ((mode >> 3) & 0070);
mode |= ((mode >> 3) & 0007);
- ret = handle_send_file(s, path, mode, buffer);
+ tmp = path;
+ if(*tmp == '/') {
+ tmp++;
+ }
+ if (is_on_system(path)) {
+ fs_config(tmp, 0, &uid, &gid, &mode, &cap);
+ }
+ ret = handle_send_file(s, path, uid, gid, mode, buffer);
}
return ret;