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 <stdlib.h>
19#include <fcntl.h>
20#include <unistd.h>
21#include <errno.h>
22#include <string.h>
23
24#include <sys/mount.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <sys/ioctl.h>
28
29#include <linux/kdev_t.h>
30
31#define LOG_TAG "Vold"
32
33#include <cutils/log.h>
34
35#include <android-base/logging.h>
36#include <android-base/stringprintf.h>
37#include <android-base/unique_fd.h>
38
39#include <sysutils/SocketClient.h>
40#include "Loop.h"
41#include "Asec.h"
42#include "VoldUtil.h"
43#include "sehandle.h"
44
45using android::base::StringPrintf;
46using android::base::unique_fd;
47
48int Loop::dumpState(SocketClient *c) {
49    int i;
50    int fd;
51    char filename[256];
52
53    for (i = 0; i < LOOP_MAX; i++) {
54        struct loop_info64 li;
55        int rc;
56
57        snprintf(filename, sizeof(filename), "/dev/block/loop%d", i);
58
59        if ((fd = open(filename, O_RDWR | O_CLOEXEC)) < 0) {
60            if (errno != ENOENT) {
61                SLOGE("Unable to open %s (%s)", filename, strerror(errno));
62            } else {
63                continue;
64            }
65            return -1;
66        }
67
68        rc = ioctl(fd, LOOP_GET_STATUS64, &li);
69        close(fd);
70        if (rc < 0 && errno == ENXIO) {
71            continue;
72        }
73
74        if (rc < 0) {
75            SLOGE("Unable to get loop status for %s (%s)", filename,
76                 strerror(errno));
77            return -1;
78        }
79        char *tmp = NULL;
80        asprintf(&tmp, "%s %d %lld:%lld %llu %lld:%lld %lld 0x%x {%s} {%s}", filename, li.lo_number,
81                MAJOR(li.lo_device), MINOR(li.lo_device), li.lo_inode, MAJOR(li.lo_rdevice),
82                        MINOR(li.lo_rdevice), li.lo_offset, li.lo_flags, li.lo_crypt_name,
83                        li.lo_file_name);
84        c->sendMsg(0, tmp, false);
85        free(tmp);
86    }
87    return 0;
88}
89
90int Loop::lookupActive(const char *id, char *buffer, size_t len) {
91    int i;
92    int fd;
93    char filename[256];
94
95    memset(buffer, 0, len);
96
97    for (i = 0; i < LOOP_MAX; i++) {
98        struct loop_info64 li;
99        int rc;
100
101        snprintf(filename, sizeof(filename), "/dev/block/loop%d", i);
102
103        if ((fd = open(filename, O_RDWR | O_CLOEXEC)) < 0) {
104            if (errno != ENOENT) {
105                SLOGE("Unable to open %s (%s)", filename, strerror(errno));
106            } else {
107                continue;
108            }
109            return -1;
110        }
111
112        rc = ioctl(fd, LOOP_GET_STATUS64, &li);
113        if (rc < 0 && errno == ENXIO) {
114            close(fd);
115            continue;
116        }
117        close(fd);
118
119        if (rc < 0) {
120            SLOGE("Unable to get loop status for %s (%s)", filename,
121                 strerror(errno));
122            return -1;
123        }
124        if (!strncmp((const char*) li.lo_crypt_name, id, LO_NAME_SIZE)) {
125            break;
126        }
127    }
128
129    if (i == LOOP_MAX) {
130        errno = ENOENT;
131        return -1;
132    }
133    strlcpy(buffer, filename, len);
134    return 0;
135}
136
137int Loop::create(const char *id, const char *loopFile, char *loopDeviceBuffer, size_t len) {
138    int i;
139    int fd;
140    char filename[256];
141
142    for (i = 0; i < LOOP_MAX; i++) {
143        struct loop_info64 li;
144        int rc;
145        char *secontext = NULL;
146
147        snprintf(filename, sizeof(filename), "/dev/block/loop%d", i);
148
149        /*
150         * The kernel starts us off with 8 loop nodes, but more
151         * are created on-demand if needed.
152         */
153        mode_t mode = 0660 | S_IFBLK;
154        unsigned int dev = (0xff & i) | ((i << 12) & 0xfff00000) | (7 << 8);
155
156        if (sehandle) {
157            rc = selabel_lookup(sehandle, &secontext, filename, S_IFBLK);
158            if (rc == 0)
159                setfscreatecon(secontext);
160        }
161
162        if (mknod(filename, mode, dev) < 0) {
163            if (errno != EEXIST) {
164                int sverrno = errno;
165                SLOGE("Error creating loop device node (%s)", strerror(errno));
166                if (secontext) {
167                    freecon(secontext);
168                    setfscreatecon(NULL);
169                }
170                errno = sverrno;
171                return -1;
172            }
173        }
174        if (secontext) {
175            freecon(secontext);
176            setfscreatecon(NULL);
177        }
178
179        if ((fd = open(filename, O_RDWR | O_CLOEXEC)) < 0) {
180            SLOGE("Unable to open %s (%s)", filename, strerror(errno));
181            return -1;
182        }
183
184        rc = ioctl(fd, LOOP_GET_STATUS64, &li);
185        if (rc < 0 && errno == ENXIO)
186            break;
187
188        close(fd);
189
190        if (rc < 0) {
191            SLOGE("Unable to get loop status for %s (%s)", filename,
192                 strerror(errno));
193            return -1;
194        }
195    }
196
197    if (i == LOOP_MAX) {
198        SLOGE("Exhausted all loop devices");
199        errno = ENOSPC;
200        return -1;
201    }
202
203    strlcpy(loopDeviceBuffer, filename, len);
204
205    int file_fd;
206
207    if ((file_fd = open(loopFile, O_RDWR | O_CLOEXEC)) < 0) {
208        SLOGE("Unable to open %s (%s)", loopFile, strerror(errno));
209        close(fd);
210        return -1;
211    }
212
213    if (ioctl(fd, LOOP_SET_FD, file_fd) < 0) {
214        SLOGE("Error setting up loopback interface (%s)", strerror(errno));
215        close(file_fd);
216        close(fd);
217        return -1;
218    }
219
220    struct loop_info64 li;
221
222    memset(&li, 0, sizeof(li));
223    strlcpy((char*) li.lo_crypt_name, id, LO_NAME_SIZE);
224    strlcpy((char*) li.lo_file_name, loopFile, LO_NAME_SIZE);
225
226    if (ioctl(fd, LOOP_SET_STATUS64, &li) < 0) {
227        SLOGE("Error setting loopback status (%s)", strerror(errno));
228        close(file_fd);
229        close(fd);
230        return -1;
231    }
232
233    close(fd);
234    close(file_fd);
235
236    return 0;
237}
238
239int Loop::create(const std::string& target, std::string& out_device) {
240    unique_fd ctl_fd(open("/dev/loop-control", O_RDWR | O_CLOEXEC));
241    if (ctl_fd.get() == -1) {
242        PLOG(ERROR) << "Failed to open loop-control";
243        return -errno;
244    }
245
246    int num = ioctl(ctl_fd.get(), LOOP_CTL_GET_FREE);
247    if (num == -1) {
248        PLOG(ERROR) << "Failed LOOP_CTL_GET_FREE";
249        return -errno;
250    }
251
252    out_device = StringPrintf("/dev/block/loop%d", num);
253
254    unique_fd target_fd(open(target.c_str(), O_RDWR | O_CLOEXEC));
255    if (target_fd.get() == -1) {
256        PLOG(ERROR) << "Failed to open " << target;
257        return -errno;
258    }
259    unique_fd device_fd(open(out_device.c_str(), O_RDWR | O_CLOEXEC));
260    if (device_fd.get() == -1) {
261        PLOG(ERROR) << "Failed to open " << out_device;
262        return -errno;
263    }
264
265    if (ioctl(device_fd.get(), LOOP_SET_FD, target_fd.get()) == -1) {
266        PLOG(ERROR) << "Failed to LOOP_SET_FD";
267        return -errno;
268    }
269
270    return 0;
271}
272
273int Loop::destroyByDevice(const char *loopDevice) {
274    int device_fd;
275
276    device_fd = open(loopDevice, O_RDONLY | O_CLOEXEC);
277    if (device_fd < 0) {
278        SLOGE("Failed to open loop (%d)", errno);
279        return -1;
280    }
281
282    if (ioctl(device_fd, LOOP_CLR_FD, 0) < 0) {
283        SLOGE("Failed to destroy loop (%d)", errno);
284        close(device_fd);
285        return -1;
286    }
287
288    close(device_fd);
289    return 0;
290}
291
292int Loop::destroyByFile(const char * /*loopFile*/) {
293    errno = ENOSYS;
294    return -1;
295}
296
297int Loop::createImageFile(const char *file, unsigned long numSectors) {
298    unique_fd fd(open(file, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, 0600));
299    if (fd.get() == -1) {
300        PLOG(ERROR) << "Failed to create image " << file;
301        return -errno;
302    }
303    if (fallocate(fd.get(), 0, 0, numSectors * 512) == -1) {
304        PLOG(WARNING) << "Failed to fallocate; falling back to ftruncate";
305        if (ftruncate(fd, numSectors * 512) == -1) {
306            PLOG(ERROR) << "Failed to ftruncate";
307            return -errno;
308        }
309    }
310    return 0;
311}
312
313int Loop::resizeImageFile(const char *file, unsigned long numSectors) {
314    int fd;
315
316    if ((fd = open(file, O_RDWR | O_CLOEXEC)) < 0) {
317        SLOGE("Error opening imagefile (%s)", strerror(errno));
318        return -1;
319    }
320
321    SLOGD("Attempting to increase size of %s to %lu sectors.", file, numSectors);
322
323    if (fallocate(fd, 0, 0, numSectors * 512)) {
324        if (errno == ENOSYS || errno == ENOTSUP) {
325            SLOGW("fallocate not found. Falling back to ftruncate.");
326            if (ftruncate(fd, numSectors * 512) < 0) {
327                SLOGE("Error truncating imagefile (%s)", strerror(errno));
328                close(fd);
329                return -1;
330            }
331        } else {
332            SLOGE("Error allocating space (%s)", strerror(errno));
333            close(fd);
334            return -1;
335        }
336    }
337    close(fd);
338    return 0;
339}
340
341int Loop::lookupInfo(const char *loopDevice, struct asec_superblock *sb, unsigned long *nr_sec) {
342    int fd;
343    struct asec_superblock buffer;
344
345    if ((fd = open(loopDevice, O_RDONLY | O_CLOEXEC)) < 0) {
346        SLOGE("Failed to open loopdevice (%s)", strerror(errno));
347        destroyByDevice(loopDevice);
348        return -1;
349    }
350
351    get_blkdev_size(fd, nr_sec);
352    if (*nr_sec == 0) {
353        SLOGE("Failed to get loop size (%s)", strerror(errno));
354        destroyByDevice(loopDevice);
355        close(fd);
356        return -1;
357    }
358
359    /*
360     * Try to read superblock.
361     */
362    memset(&buffer, 0, sizeof(struct asec_superblock));
363    if (lseek(fd, ((*nr_sec - 1) * 512), SEEK_SET) < 0) {
364        SLOGE("lseek failed (%s)", strerror(errno));
365        close(fd);
366        destroyByDevice(loopDevice);
367        return -1;
368    }
369    if (read(fd, &buffer, sizeof(struct asec_superblock)) != sizeof(struct asec_superblock)) {
370        SLOGE("superblock read failed (%s)", strerror(errno));
371        close(fd);
372        destroyByDevice(loopDevice);
373        return -1;
374    }
375    close(fd);
376
377    /*
378     * Superblock successfully read. Copy to caller's struct.
379     */
380    memcpy(sb, &buffer, sizeof(struct asec_superblock));
381    return 0;
382}
383