• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <fs_dm.h>
17 #include "securec.h"
18 #include "beget_ext.h"
19 #include <linux/dm-ioctl.h>
20 #include <sys/ioctl.h>
21 #include <sys/types.h>
22 #include <sys/sysmacros.h>
23 #include <fcntl.h>
24 #include <stdlib.h>
25 #include <errno.h>
26 #include "ueventd.h"
27 #include "ueventd_socket.h"
28 #include <limits.h>
29 
30 #ifdef __cplusplus
31 #if __cplusplus
32 extern "C" {
33 #endif
34 #endif
35 
36 const char g_dmType[MAXNUMTYPE][MAX_WORDS_LEN] = {"verity", "linear", "snapshot", "snapshot-merge"};
37 
InitDmIo(struct dm_ioctl * io,const char * devName)38 int InitDmIo(struct dm_ioctl *io, const char *devName)
39 {
40     errno_t err;
41 
42     err = memset_s(io, sizeof(*io), 0, sizeof(*io));
43     if (err != EOK) {
44         BEGET_LOGE("memset io, ret=%d", err);
45         return -1;
46     }
47 
48     io->version[0] = DM_VERSION0;
49     io->version[1] = DM_VERSION1;
50     io->version[2] = DM_VERSION2;
51     io->data_size = sizeof(*io);
52     io->data_start = 0;
53 
54     if (devName == NULL) {
55         return 0;
56     }
57 
58     err = strcpy_s(io->name, sizeof(io->name), devName);
59     if (err != EOK) {
60         BEGET_LOGE("cp devName, ret=%d", err);
61         return -1;
62     }
63 
64     return 0;
65 }
66 
CreateDmDev(int fd,const char * devName)67 int CreateDmDev(int fd, const char *devName)
68 {
69     int rc;
70     struct dm_ioctl io;
71 
72     rc = InitDmIo(&io, devName);
73     if (rc != 0) {
74         return rc;
75     }
76 
77     rc = ioctl(fd, DM_DEV_CREATE, &io);
78     if (rc != 0) {
79         BEGET_LOGE("error, DM_DEV_CREATE failed for %s, ret=%d", devName, rc);
80         return rc;
81     }
82 
83     return 0;
84 }
85 
LoadDmDeviceTable(int fd,const char * devName,DmVerityTarget * target,int dmTypeIdx)86 int LoadDmDeviceTable(int fd, const char *devName, DmVerityTarget *target, int dmTypeIdx)
87 {
88     int rc;
89     errno_t err;
90     char *parasBuf = NULL;
91     size_t parasTotalSize;
92     struct dm_ioctl *io = NULL;
93     struct dm_target_spec *ts = NULL;
94     char *paras = NULL;
95 
96     FS_DM_RETURN_ERR_IF_NULL(target);
97     FS_DM_RETURN_ERR_IF_NULL(target->paras);
98     if (dmTypeIdx >= MAXNUMTYPE || dmTypeIdx < 0) {
99         BEGET_LOGE("dmTypeIdx error dmTypeIdx %d", dmTypeIdx);
100         return -1;
101     }
102 
103     parasTotalSize = DM_ALIGN(sizeof(*io) + sizeof(*ts) + target->paras_len + 1);
104     parasBuf = calloc(1, parasTotalSize);
105     if (parasBuf == NULL) {
106         BEGET_LOGE("error, calloc dm table fail");
107         return -1;
108     }
109 
110     io = (struct dm_ioctl *)parasBuf;
111     ts = (struct dm_target_spec *)(parasBuf + sizeof(*io));
112     paras = parasBuf + sizeof(*io) + sizeof((*ts));
113 
114     do {
115         rc = InitDmIo(io, devName);
116         if (rc != 0) {
117             BEGET_LOGE("error 0x%x, init dm io", rc);
118             break;
119         }
120 
121         io->data_size = parasTotalSize;
122         io->data_start = sizeof(*io);
123         io->target_count = 1;
124         if (dmTypeIdx != SNAPSHOT) {
125             io->flags |= DM_READONLY_FLAG;
126         }
127 
128         ts->status = 0;
129         ts->sector_start = target->start;
130         ts->length = target->length;
131         err = strcpy_s(ts->target_type, sizeof(ts->target_type), g_dmType[dmTypeIdx]);
132         if (err != EOK) {
133             rc = -1;
134             BEGET_LOGE("error 0x%x, cp target type", err);
135             break;
136         }
137         BEGET_LOGI("get target type is %s", ts->target_type);
138         err = strcpy_s(paras, target->paras_len + 1, target->paras);
139         if (err != EOK) {
140             rc = -1;
141             BEGET_LOGE("error 0x%x, cp target paras", err);
142             break;
143         }
144 
145         ts->next = parasTotalSize - sizeof(*io);
146 
147         rc = ioctl(fd, DM_TABLE_LOAD, io);
148         if (rc != 0) {
149             BEGET_LOGE("error 0x%x, DM_TABLE_LOAD failed for %s", rc, devName);
150             break;
151         }
152     } while (0);
153 
154     free(parasBuf);
155 
156     return rc;
157 }
158 
ActiveDmDevice(int fd,const char * devName)159 int ActiveDmDevice(int fd, const char *devName)
160 {
161     int rc;
162     struct dm_ioctl io;
163 
164     rc = InitDmIo(&io, devName);
165     if (rc != 0) {
166         return rc;
167     }
168 
169     io.flags |= DM_READONLY_FLAG;
170 
171     rc = ioctl(fd, DM_DEV_SUSPEND, &io);
172     if (rc != 0) {
173         BEGET_LOGE("error, DM_TABLE_SUSPEND for %s, ret=%d", devName, rc);
174         return rc;
175     }
176 
177     return 0;
178 }
179 
GetDmDevPath(int fd,char ** dmDevPath,const char * devName)180 int GetDmDevPath(int fd, char **dmDevPath, const char *devName)
181 {
182     int rc;
183     char *path = NULL;
184     size_t path_len = strlen(DM_DEVICE_PATH_PREFIX) + 32;
185     unsigned int dev_num;
186     struct dm_ioctl io;
187 
188     rc = InitDmIo(&io, devName);
189     if (rc != 0) {
190         BEGET_LOGE("error 0x%x, init Dm io", rc);
191         return rc;
192     }
193 
194     rc = ioctl(fd, DM_DEV_STATUS, &io);
195     if (rc != 0) {
196         BEGET_LOGE("error, DM_DEV_STATUS for %s, ret=%d", devName, rc);
197         return rc;
198     }
199 
200     dev_num = minor(io.dev);
201 
202     path = calloc(1, path_len);
203     if (path == NULL) {
204         BEGET_LOGE("error, alloc dm dev path");
205         return -1;
206     }
207 
208     rc = snprintf_s(path, path_len, path_len - 1, "%s%u", DM_DEVICE_PATH_PREFIX, dev_num);
209     if (rc < 0) {
210         BEGET_LOGE("error 0x%x, cp dm dev path", rc);
211         free(path);
212         return -1;
213     }
214 
215     *dmDevPath = path;
216 
217     return 0;
218 }
219 
FsDmCreateDevice(char ** dmDevPath,const char * devName,DmVerityTarget * target)220 int FsDmCreateDevice(char **dmDevPath, const char *devName, DmVerityTarget *target)
221 {
222     int rc;
223     int fd = -1;
224 
225     fd = open(DEVICE_MAPPER_PATH, O_RDWR | O_CLOEXEC);
226     if (fd < 0) {
227         BEGET_LOGE("error 0x%x, open %s", errno, DEVICE_MAPPER_PATH);
228         return -1;
229     }
230 
231     rc = CreateDmDev(fd, devName);
232     if (rc != 0) {
233         BEGET_LOGE("error 0x%x, create dm device fail", rc);
234         close(fd);
235         return rc;
236     }
237 
238     rc = LoadDmDeviceTable(fd, devName, target, VERIFY);
239     if (rc != 0) {
240         BEGET_LOGE("error 0x%x, load device table fail", rc);
241         close(fd);
242         return rc;
243     }
244 
245     rc = ActiveDmDevice(fd, devName);
246     if (rc != 0) {
247         BEGET_LOGE("error 0x%x, active device fail", rc);
248         close(fd);
249         return rc;
250     }
251 
252     rc = GetDmDevPath(fd, dmDevPath, devName);
253     if (rc != 0) {
254         BEGET_LOGE("error 0x%x, get dm dev fail", rc);
255         close(fd);
256         return rc;
257     }
258     close(fd);
259     return 0;
260 }
261 
FsDmInitDmDev(char * devPath,bool useSocket)262 int FsDmInitDmDev(char *devPath, bool useSocket)
263 {
264     int rc;
265     char dmDevPath[PATH_MAX] = {0};
266     char *devName = NULL;
267 
268     if (devPath == NULL) {
269         BEGET_LOGE("error, devPath is NULL");
270         return -1;
271     }
272 
273     devName = basename(devPath);
274 
275     rc = snprintf_s(&dmDevPath[0], sizeof(dmDevPath), sizeof(dmDevPath) - 1, "%s%s", "/sys/block/", devName);
276     if (rc < 0) {
277         BEGET_LOGE("error 0x%x, format dm dev", rc);
278         return rc;
279     }
280 
281     int ueventSockFd = -1;
282     if (useSocket) {
283         ueventSockFd = UeventdSocketInit();
284         if (ueventSockFd < 0) {
285             BEGET_LOGE("error, Failed to create uevent socket");
286             return -1;
287         }
288     }
289     char **devices = (char **)calloc(1, sizeof(char *));
290     if (devices == NULL) {
291         BEGET_LOGE("Failed calloc err=%d", errno);
292         return -1;
293     }
294 
295     devices[0] = strdup(devPath);
296     if (devices[0] == NULL) {
297         BEGET_LOGE("Failed to strdup devPath");
298         free(devices);
299         return -1;
300     }
301     BEGET_LOGI("FsDmInitDmDev dmDevPath %s devices %s", &dmDevPath[0], devices[0]);
302     RetriggerDmUeventByPath(ueventSockFd, &dmDevPath[0], devices, 1);
303     free(devices[0]);
304     free(devices);
305 
306     close(ueventSockFd);
307 
308     return 0;
309 }
310 
FsDmRemoveDevice(const char * devName)311 int FsDmRemoveDevice(const char *devName)
312 {
313     int rc;
314     int fd = -1;
315     struct dm_ioctl io;
316 
317     fd = open(DEVICE_MAPPER_PATH, O_RDWR | O_CLOEXEC);
318     if (fd < 0) {
319         BEGET_LOGE("error 0x%x, open %s", errno, DEVICE_MAPPER_PATH);
320         return -1;
321     }
322 
323     rc = InitDmIo(&io, devName);
324     if (rc != 0) {
325         close(fd);
326         BEGET_LOGE("error 0x%x, init dm io", rc);
327         return -1;
328     }
329 
330     io.flags |= DM_READONLY_FLAG;
331 
332     rc = ioctl(fd, DM_DEV_REMOVE, &io);
333     if (rc != 0) {
334         close(fd);
335         BEGET_LOGE("error, DM_DEV_REMOVE failed for %s, ret=%d", devName, rc);
336         return -1;
337     }
338 
339     close(fd);
340     return 0;
341 }
342 
DmGetDeviceName(int fd,const char * devName,char * outDevName,const uint64_t outDevNameLen)343 int DmGetDeviceName(int fd, const char *devName, char *outDevName, const uint64_t outDevNameLen)
344 {
345     int rc;
346     char *path = NULL;
347     size_t pathLen = strlen(DM_DEVICE_PATH_PREFIX) + 32;
348     struct dm_ioctl io;
349     rc = InitDmIo(&io, devName);
350     if (rc != 0) {
351         BEGET_LOGE("init dm io failed");
352         return rc;
353     }
354 
355     rc = ioctl(fd, DM_DEV_STATUS, &io);
356     if (rc != 0) {
357         BEGET_LOGE("get  DM_DEV_STATUS failed");
358         return rc;
359     }
360 
361     int devNum = (io.dev & 0xff) | ((io.dev >> 12) & 0xff00);
362     path = calloc(1, pathLen);
363     if (path == NULL) {
364         BEGET_LOGE("calloc path failed");
365         return -1;
366     }
367 
368     rc = snprintf_s(path, pathLen, pathLen - 1, "%s%d", DM_DEVICE_PATH_PREFIX, devNum);
369     if (rc < 0) {
370         BEGET_LOGE("copy dm path failed");
371         free(path);
372         path = NULL;
373         return rc;
374     }
375 
376     rc = memcpy_s(outDevName, outDevNameLen, path, pathLen);
377     if (rc < 0) {
378         BEGET_LOGE("copy dm path failed");
379     }
380     BEGET_LOGI("dm get device outDevName %s, devNum %d", path, devNum);
381     free(path);
382     path = NULL;
383     return rc;
384 }
385 
FsDmCreateLinearDevice(const char * devName,char * dmBlkName,uint64_t dmBlkNameLen,DmVerityTarget * target)386 int FsDmCreateLinearDevice(const char *devName, char *dmBlkName, uint64_t dmBlkNameLen, DmVerityTarget *target)
387 {
388     int rc;
389     int fd = -1;
390     fd = open(DEVICE_MAPPER_PATH, O_RDWR | O_CLOEXEC);
391     if (fd < 0) {
392         BEGET_LOGE("open mapper path failed");
393         return -1;
394     }
395 
396     rc = CreateDmDev(fd, devName);
397     if (rc) {
398         BEGET_LOGE("create dm device failed");
399         close(fd);
400         return -1;
401     }
402 
403     rc = DmGetDeviceName(fd, devName, dmBlkName, dmBlkNameLen);
404     if (rc) {
405         BEGET_LOGE("get dm device name failed");
406         close(fd);
407         return -1;
408     }
409 
410     rc = LoadDmDeviceTable(fd, devName, target, LINEAR);
411     if (rc) {
412         BEGET_LOGE("load dm device name failed");
413         close(fd);
414         return -1;
415     }
416 
417     rc = ActiveDmDevice(fd, devName);
418     if (rc) {
419         BEGET_LOGE("active dm device name failed");
420         close(fd);
421         return -1;
422     }
423     close(fd);
424     BEGET_LOGI("fs create rofs linear device success, dev is [%s]", devName);
425     return 0;
426 }
427 
GetDmStatusInfo(const char * name,struct dm_ioctl * io)428 bool GetDmStatusInfo(const char *name, struct dm_ioctl *io)
429 {
430     int fd = open(DEVICE_MAPPER_PATH, O_RDWR | O_CLOEXEC);
431     if (fd < 0) {
432         BEGET_LOGE("error 0x%x, open %s", errno, DEVICE_MAPPER_PATH);
433         return false;
434     }
435     int rc = InitDmIo(io, name);
436     if (rc != 0) {
437         close(fd);
438         return false;
439     }
440     if (ioctl(fd, DM_DEV_STATUS, io) != 0) {
441         BEGET_LOGE("DM_DEV_STATUS failed for %s\n", name);
442         close(fd);
443         return false;
444     }
445     close(fd);
446     return true;
447 }
448 
449 
450 #ifdef __cplusplus
451 #if __cplusplus
452 }
453 #endif
454 #endif
455