• 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 #define DM_VERSION0 (4)
37 #define DM_VERSION1 (0)
38 #define DM_VERSION2 (0)
39 #define DM_ALIGN_MASK (7)
40 #define DM_ALIGN(x) (((x) + DM_ALIGN_MASK) & ~DM_ALIGN_MASK)
41 #define DEVICE_MAPPER_PATH  "/dev/mapper/control"
42 #define DM_DEVICE_PATH_PREFIX  "/dev/block/dm-"
43 
44 #define FS_DM_RETURN_ERR_IF_NULL(__ptr)                 \
45     do {                                                \
46         if ((__ptr) == NULL) {                          \
47             BEGET_LOGE("error, %s is NULL\n", #__ptr); \
48             return -1;                                  \
49         }                                               \
50     } while (0)
51 
InitDmIo(struct dm_ioctl * io,const char * devName)52 static int InitDmIo(struct dm_ioctl *io, const char *devName)
53 {
54     errno_t err;
55 
56     err = memset_s(io, sizeof(*io), 0, sizeof(*io));
57     if (err != EOK) {
58         BEGET_LOGE("memset io, ret=%d", err);
59         return -1;
60     }
61 
62     io->version[0] = DM_VERSION0;
63     io->version[1] = DM_VERSION1;
64     io->version[2] = DM_VERSION2;
65     io->data_size = sizeof(*io);
66     io->data_start = 0;
67 
68     if (devName == NULL) {
69         return 0;
70     }
71 
72     err = strcpy_s(io->name, sizeof(io->name), devName);
73     if (err != EOK) {
74         BEGET_LOGE("cp devName, ret=%d", err);
75         return -1;
76     }
77 
78     return 0;
79 }
80 
CreateDmDevice(int fd,const char * devName)81 static int CreateDmDevice(int fd, const char *devName)
82 {
83     int rc;
84     struct dm_ioctl io;
85 
86     rc = InitDmIo(&io, devName);
87     if (rc != 0) {
88         return rc;
89     }
90 
91     rc = ioctl(fd, DM_DEV_CREATE, &io);
92     if (rc != 0) {
93         BEGET_LOGE("error, DM_DEV_CREATE failed for %s, ret=%d", devName, rc);
94         return rc;
95     }
96 
97     return 0;
98 }
99 
LoadDmDeviceTable(int fd,const char * devName,DmVerityTarget * target)100 static int LoadDmDeviceTable(int fd, const char *devName,
101                              DmVerityTarget *target)
102 {
103     int rc;
104     errno_t err;
105     char *parasBuf = NULL;
106     size_t parasTotalSize;
107     struct dm_ioctl *io = NULL;
108     struct dm_target_spec *ts = NULL;
109     char *paras = NULL;
110 
111     FS_DM_RETURN_ERR_IF_NULL(target);
112     FS_DM_RETURN_ERR_IF_NULL(target->paras);
113 
114     parasTotalSize = DM_ALIGN(sizeof(*io) + sizeof(*ts) + target->paras_len + 1);
115     parasBuf = calloc(1, parasTotalSize);
116     if (parasBuf == NULL) {
117         BEGET_LOGE("error, calloc dm table fail");
118         return -1;
119     }
120 
121     io = (struct dm_ioctl *)parasBuf;
122     ts = (struct dm_target_spec *)(parasBuf + sizeof(*io));
123     paras = parasBuf + sizeof(*io) + sizeof((*ts));
124 
125     do {
126         rc = InitDmIo(io, devName);
127         if (rc != 0) {
128             BEGET_LOGE("error 0x%x, init dm io", rc);
129             break;
130         }
131 
132         io->data_size = parasTotalSize;
133         io->data_start = sizeof(*io);
134         io->target_count = 1;
135         io->flags |= DM_READONLY_FLAG;
136 
137         ts->status = 0;
138         ts->sector_start = target->start;
139         ts->length = target->length;
140 
141         err = strcpy_s(ts->target_type, sizeof(ts->target_type), "verity");
142         if (err != EOK) {
143             rc = -1;
144             BEGET_LOGE("error 0x%x, cp target type", err);
145             break;
146         }
147 
148         err = strcpy_s(paras, target->paras_len + 1,target->paras);
149         if (err != EOK) {
150             rc = -1;
151             BEGET_LOGE("error 0x%x, cp target paras", err);
152             break;
153         }
154 
155         ts->next = parasTotalSize - sizeof(*io);
156 
157         rc = ioctl(fd, DM_TABLE_LOAD, io);
158         if (rc != 0) {
159             BEGET_LOGE("error 0x%x, DM_TABLE_LOAD failed for %s", rc, devName);
160             break;
161         }
162     } while (0);
163 
164     free(parasBuf);
165 
166     return rc;
167 }
168 
ActiveDmDevice(int fd,const char * devName)169 static int ActiveDmDevice(int fd, const char *devName)
170 {
171     int rc;
172     struct dm_ioctl io;
173 
174     rc = InitDmIo(&io, devName);
175     if (rc != 0) {
176         return rc;
177     }
178 
179     io.flags |= DM_READONLY_FLAG;
180 
181     rc = ioctl(fd, DM_DEV_SUSPEND, &io);
182     if (rc != 0) {
183         BEGET_LOGE("error, DM_TABLE_SUSPEND for %s, ret=%d", devName, rc);
184         return rc;
185     }
186 
187     return 0;
188 }
189 
GetDmDevPath(int fd,char ** dmDevPath,const char * devName)190 int GetDmDevPath(int fd, char **dmDevPath, const char *devName)
191 {
192     int rc;
193     char *path = NULL;
194     size_t path_len = strlen(DM_DEVICE_PATH_PREFIX) + 32;
195     unsigned int dev_num;
196     struct dm_ioctl io;
197 
198     rc = InitDmIo(&io, devName);
199     if (rc != 0) {
200         BEGET_LOGE("error 0x%x, init Dm io", rc);
201         return rc;
202     }
203 
204     rc = ioctl(fd, DM_DEV_STATUS, &io);
205     if (rc != 0) {
206         BEGET_LOGE("error, DM_DEV_STATUS for %s, ret=%d", devName, rc);
207         return rc;
208     }
209 
210     dev_num = minor(io.dev);
211 
212     path = calloc(1, path_len);
213     if (path == NULL) {
214         BEGET_LOGE("error, alloc dm dev path");
215         return -1;
216     }
217 
218     rc = snprintf_s(path, path_len, path_len - 1, "%s%u", DM_DEVICE_PATH_PREFIX, dev_num);
219     if (rc < 0) {
220         BEGET_LOGE("error 0x%x, cp dm dev path", rc);
221         free(path);
222         return -1;
223     }
224 
225     *dmDevPath = path;
226 
227     return 0;
228 }
229 
FsDmCreateDevice(char ** dmDevPath,const char * devName,DmVerityTarget * target)230 int FsDmCreateDevice(char **dmDevPath, const char *devName, DmVerityTarget *target)
231 {
232     int rc;
233     int fd = -1;
234 
235     fd = open(DEVICE_MAPPER_PATH, O_RDWR | O_CLOEXEC);
236     if (fd < 0) {
237         BEGET_LOGE("error 0x%x, open %s", errno, DEVICE_MAPPER_PATH);
238         return -1;
239     }
240 
241     rc = CreateDmDevice(fd, devName);
242     if (rc != 0) {
243         BEGET_LOGE("error 0x%x, create dm device fail", rc);
244         return rc;
245     }
246 
247     rc = LoadDmDeviceTable(fd, devName, target);
248     if (rc != 0) {
249         BEGET_LOGE("error 0x%x, load device table fail", rc);
250         return rc;
251     }
252 
253     rc = ActiveDmDevice(fd, devName);
254     if (rc != 0) {
255         BEGET_LOGE("error 0x%x, active device fail", rc);
256         return rc;
257     }
258 
259     rc = GetDmDevPath(fd, dmDevPath, devName);
260     if (rc != 0) {
261         BEGET_LOGE("error 0x%x, get dm dev fail", rc);
262         return rc;
263     }
264 
265     return 0;
266 }
267 
FsDmInitDmDev(char * devPath)268 int FsDmInitDmDev(char *devPath)
269 {
270     int rc;
271     char dmDevPath[PATH_MAX] = {0};
272     char *devName = NULL;
273 
274     if (devPath == NULL) {
275         BEGET_LOGE("error, devPath is NULL");
276         return -1;
277     }
278 
279     devName = basename(devPath);
280 
281     rc = snprintf_s(&dmDevPath[0], sizeof(dmDevPath), sizeof(dmDevPath) - 1, "%s%s", "/sys/block/", devName);
282     if (rc < 0) {
283         BEGET_LOGE("error 0x%x, format dm dev", rc);
284         return rc;
285     }
286 
287     int ueventSockFd = UeventdSocketInit();
288     if (ueventSockFd < 0) {
289         BEGET_LOGE("error, Failed to create uevent socket");
290         return -1;
291     }
292 
293     RetriggerUeventByPath(ueventSockFd, &dmDevPath[0]);
294 
295     close(ueventSockFd);
296 
297     return 0;
298 }
299 
300 #ifdef __cplusplus
301 #if __cplusplus
302 }
303 #endif
304 #endif
305