OSDN Git Service

Prevent buffer overflows.
[android-x86/system-vold.git] / Loop.cpp
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <errno.h>
21 #include <string.h>
22
23 #include <sys/types.h>
24 #include <sys/stat.h>
25
26 #include <linux/kdev_t.h>
27
28 #define LOG_TAG "Vold"
29
30 #include <cutils/log.h>
31
32 #include <sysutils/SocketClient.h>
33 #include "Loop.h"
34
35 int Loop::dumpState(SocketClient *c) {
36     int i;
37     int fd;
38     char filename[256];
39
40     for (i = 0; i < LOOP_MAX; i++) {
41         struct loop_info64 li;
42         int rc;
43
44         sprintf(filename, "/dev/block/loop%d", i);
45
46         if ((fd = open(filename, O_RDWR)) < 0) {
47             if (errno != ENOENT) {
48                 SLOGE("Unable to open %s (%s)", filename, strerror(errno));
49             } else {
50                 continue;
51             }
52             return -1;
53         }
54
55         rc = ioctl(fd, LOOP_GET_STATUS64, &li);
56         close(fd);
57         if (rc < 0 && errno == ENXIO) {
58             continue;
59         }
60
61         if (rc < 0) {
62             SLOGE("Unable to get loop status for %s (%s)", filename,
63                  strerror(errno));
64             return -1;
65         }
66         char *tmp = NULL;
67         asprintf(&tmp, "%s %d %lld:%lld %llu %lld:%lld %lld 0x%x {%s} {%s}", filename, li.lo_number,
68                 MAJOR(li.lo_device), MINOR(li.lo_device), li.lo_inode, MAJOR(li.lo_rdevice),
69                         MINOR(li.lo_rdevice), li.lo_offset, li.lo_flags, li.lo_crypt_name,
70                         li.lo_file_name);
71         c->sendMsg(0, tmp, false);
72         free(tmp);
73     }
74     return 0;
75 }
76
77 int Loop::lookupActive(const char *id, char *buffer, size_t len) {
78     int i;
79     int fd;
80     char filename[256];
81
82     memset(buffer, 0, len);
83
84     for (i = 0; i < LOOP_MAX; i++) {
85         struct loop_info64 li;
86         int rc;
87
88         sprintf(filename, "/dev/block/loop%d", i);
89
90         if ((fd = open(filename, O_RDWR)) < 0) {
91             if (errno != ENOENT) {
92                 SLOGE("Unable to open %s (%s)", filename, strerror(errno));
93             } else {
94                 continue;
95             }
96             return -1;
97         }
98
99         rc = ioctl(fd, LOOP_GET_STATUS64, &li);
100         close(fd);
101         if (rc < 0 && errno == ENXIO) {
102             continue;
103         }
104
105         if (rc < 0) {
106             SLOGE("Unable to get loop status for %s (%s)", filename,
107                  strerror(errno));
108             return -1;
109         }
110         if (!strncmp((const char*) li.lo_crypt_name, id, LO_NAME_SIZE)) {
111             break;
112         }
113     }
114
115     if (i == LOOP_MAX) {
116         errno = ENOENT;
117         return -1;
118     }
119     strncpy(buffer, filename, len -1);
120     return 0;
121 }
122
123 int Loop::create(const char *id, const char *loopFile, char *loopDeviceBuffer, size_t len) {
124     int i;
125     int fd;
126     char filename[256];
127
128     for (i = 0; i < LOOP_MAX; i++) {
129         struct loop_info li;
130         int rc;
131
132         sprintf(filename, "/dev/block/loop%d", i);
133
134         /*
135          * The kernel starts us off with 8 loop nodes, but more
136          * are created on-demand if needed.
137          */
138         mode_t mode = 0660 | S_IFBLK;
139         unsigned int dev = (0xff & i) | ((i << 12) & 0xfff00000) | (7 << 8);
140         if (mknod(filename, mode, dev) < 0) {
141             if (errno != EEXIST) {
142                 SLOGE("Error creating loop device node (%s)", strerror(errno));
143                 return -1;
144             }
145         }
146
147         if ((fd = open(filename, O_RDWR)) < 0) {
148             SLOGE("Unable to open %s (%s)", filename, strerror(errno));
149             return -1;
150         }
151
152         rc = ioctl(fd, LOOP_GET_STATUS, &li);
153         if (rc < 0 && errno == ENXIO)
154             break;
155
156         close(fd);
157
158         if (rc < 0) {
159             SLOGE("Unable to get loop status for %s (%s)", filename,
160                  strerror(errno));
161             return -1;
162         }
163     }
164
165     if (i == LOOP_MAX) {
166         SLOGE("Exhausted all loop devices");
167         errno = ENOSPC;
168         return -1;
169     }
170
171     strncpy(loopDeviceBuffer, filename, len -1);
172
173     int file_fd;
174
175     if ((file_fd = open(loopFile, O_RDWR)) < 0) {
176         SLOGE("Unable to open %s (%s)", loopFile, strerror(errno));
177         close(fd);
178         return -1;
179     }
180
181     if (ioctl(fd, LOOP_SET_FD, file_fd) < 0) {
182         SLOGE("Error setting up loopback interface (%s)", strerror(errno));
183         close(file_fd);
184         close(fd);
185         return -1;
186     }
187
188     struct loop_info64 li;
189
190     memset(&li, 0, sizeof(li));
191     strlcpy((char*) li.lo_crypt_name, id, LO_NAME_SIZE);
192     strlcpy((char*) li.lo_file_name, loopFile, LO_NAME_SIZE);
193
194     if (ioctl(fd, LOOP_SET_STATUS64, &li) < 0) {
195         SLOGE("Error setting loopback status (%s)", strerror(errno));
196         close(file_fd);
197         close(fd);
198         return -1;
199     }
200
201     close(fd);
202     close(file_fd);
203
204     return 0;
205 }
206
207 int Loop::destroyByDevice(const char *loopDevice) {
208     int device_fd;
209
210     device_fd = open(loopDevice, O_RDONLY);
211     if (device_fd < 0) {
212         SLOGE("Failed to open loop (%d)", errno);
213         return -1;
214     }
215
216     if (ioctl(device_fd, LOOP_CLR_FD, 0) < 0) {
217         SLOGE("Failed to destroy loop (%d)", errno);
218         close(device_fd);
219         return -1;
220     }
221
222     close(device_fd);
223     return 0;
224 }
225
226 int Loop::destroyByFile(const char *loopFile) {
227     errno = ENOSYS;
228     return -1;
229 }
230
231 int Loop::createImageFile(const char *file, unsigned int numSectors) {
232     int fd;
233
234     if ((fd = creat(file, 0600)) < 0) {
235         SLOGE("Error creating imagefile (%s)", strerror(errno));
236         return -1;
237     }
238
239     if (ftruncate(fd, numSectors * 512) < 0) {
240         SLOGE("Error truncating imagefile (%s)", strerror(errno));
241         close(fd);
242         return -1;
243     }
244     close(fd);
245     return 0;
246 }