• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Aucun tag

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

system/corennnnn


Commit MetaInfo

Révision2895e11453da7afc326864a097ff59833a0bffea (tree)
l'heure2016-07-16 04:34:06
AuteurMark Salyzyn <salyzyn@goog...>
CommiterSteve Kondik

Message de Log

libcutils: ashmem check fd validity

- collect st_rdev on open, or when required, for /dev/ashmem.
- check in all cases if fd is a character device and matches rdev.
- requires that we have open, read and write access to /dev/ashmem

to check, assumption being that if we can not, then we have no
right playing with the associated misdirected file descriptor.

NB: ashmem libcutil library entry points can no longer be called in

signal context.

Bug: 26871259
Change-Id: I9a17e33317a9be795131473a51c16f761b5f7407

Change Summary

Modification

--- a/libcutils/ashmem-dev.c
+++ b/libcutils/ashmem-dev.c
@@ -22,6 +22,7 @@
2222
2323 #include <errno.h>
2424 #include <fcntl.h>
25+#include <pthread.h>
2526 #include <string.h>
2627 #include <sys/ioctl.h>
2728 #include <sys/stat.h>
@@ -34,6 +35,89 @@
3435
3536 #define ASHMEM_DEVICE "/dev/ashmem"
3637
38+/* ashmem identity */
39+static dev_t __ashmem_rdev;
40+/*
41+ * If we trigger a signal handler in the middle of locked activity and the
42+ * signal handler calls ashmem, we could get into a deadlock state.
43+ */
44+static pthread_mutex_t __ashmem_lock = PTHREAD_MUTEX_INITIALIZER;
45+
46+/* logistics of getting file descriptor for ashmem */
47+static int __ashmem_open_locked()
48+{
49+ int ret;
50+ struct stat st;
51+
52+ int fd = TEMP_FAILURE_RETRY(open(ASHMEM_DEVICE, O_RDWR));
53+ if (fd < 0) {
54+ return fd;
55+ }
56+
57+ ret = TEMP_FAILURE_RETRY(fstat(fd, &st));
58+ if (ret < 0) {
59+ int save_errno = errno;
60+ close(fd);
61+ errno = save_errno;
62+ return ret;
63+ }
64+ if (!S_ISCHR(st.st_mode) || !st.st_rdev) {
65+ close(fd);
66+ errno = ENOTTY;
67+ return -1;
68+ }
69+
70+ __ashmem_rdev = st.st_rdev;
71+ return fd;
72+}
73+
74+static int __ashmem_open()
75+{
76+ int fd;
77+
78+ pthread_mutex_lock(&__ashmem_lock);
79+ fd = __ashmem_open_locked();
80+ pthread_mutex_unlock(&__ashmem_lock);
81+
82+ return fd;
83+}
84+
85+/* Make sure file descriptor references ashmem, negative number means false */
86+static int __ashmem_is_ashmem(int fd)
87+{
88+ dev_t rdev;
89+ struct stat st;
90+
91+ if (TEMP_FAILURE_RETRY(fstat(fd, &st)) < 0) {
92+ return -1;
93+ }
94+
95+ if (S_ISCHR(st.st_mode) && st.st_rdev) {
96+ pthread_mutex_lock(&__ashmem_lock);
97+ rdev = __ashmem_rdev;
98+ if (rdev) {
99+ pthread_mutex_unlock(&__ashmem_lock);
100+ } else {
101+ int fd = __ashmem_open_locked();
102+ if (fd < 0) {
103+ pthread_mutex_unlock(&__ashmem_lock);
104+ return -1;
105+ }
106+ rdev = __ashmem_rdev;
107+ pthread_mutex_unlock(&__ashmem_lock);
108+
109+ close(fd);
110+ }
111+
112+ if (st.st_rdev == rdev) {
113+ return 0;
114+ }
115+ }
116+
117+ errno = ENOTTY;
118+ return -1;
119+}
120+
37121 /*
38122 * ashmem_create_region - creates a new ashmem region and returns the file
39123 * descriptor, or <0 on error
@@ -45,7 +129,7 @@ int ashmem_create_region(const char *name, size_t size)
45129 {
46130 int ret, save_errno;
47131
48- int fd = TEMP_FAILURE_RETRY(open(ASHMEM_DEVICE, O_RDWR));
132+ int fd = __ashmem_open();
49133 if (fd < 0) {
50134 return fd;
51135 }
@@ -76,22 +160,44 @@ error:
76160
77161 int ashmem_set_prot_region(int fd, int prot)
78162 {
163+ int ret = __ashmem_is_ashmem(fd);
164+ if (ret < 0) {
165+ return ret;
166+ }
167+
79168 return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_SET_PROT_MASK, prot));
80169 }
81170
82171 int ashmem_pin_region(int fd, size_t offset, size_t len)
83172 {
84173 struct ashmem_pin pin = { offset, len };
174+
175+ int ret = __ashmem_is_ashmem(fd);
176+ if (ret < 0) {
177+ return ret;
178+ }
179+
85180 return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_PIN, &pin));
86181 }
87182
88183 int ashmem_unpin_region(int fd, size_t offset, size_t len)
89184 {
90185 struct ashmem_pin pin = { offset, len };
186+
187+ int ret = __ashmem_is_ashmem(fd);
188+ if (ret < 0) {
189+ return ret;
190+ }
191+
91192 return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_UNPIN, &pin));
92193 }
93194
94195 int ashmem_get_size_region(int fd)
95196 {
197+ int ret = __ashmem_is_ashmem(fd);
198+ if (ret < 0) {
199+ return ret;
200+ }
201+
96202 return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_GET_SIZE, NULL));
97203 }