]> git.proxmox.com Git - mirror_qemu.git/blame - hw/virtio-9p-local.c
virtio-9p: Implemented Security model for lstat and fstat
[mirror_qemu.git] / hw / virtio-9p-local.c
CommitLineData
9f107513
AL
1/*
2 * Virtio 9p Posix callback
3 *
4 * Copyright IBM, Corp. 2010
5 *
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
11 *
12 */
13#include "virtio.h"
14#include "virtio-9p.h"
c494dd6f 15#include <arpa/inet.h>
131dcb25
AL
16#include <pwd.h>
17#include <grp.h>
c494dd6f
AL
18#include <sys/socket.h>
19#include <sys/un.h>
758e8e38 20#include <attr/xattr.h>
131dcb25
AL
21
22static const char *rpath(FsContext *ctx, const char *path)
23{
24 /* FIXME: so wrong... */
25 static char buffer[4096];
26 snprintf(buffer, sizeof(buffer), "%s/%s", ctx->fs_root, path);
27 return buffer;
28}
29
1237ad76
VJ
30
31static int local_lstat(FsContext *fs_ctx, const char *path, struct stat *stbuf)
131dcb25 32{
1237ad76
VJ
33 int err;
34 err = lstat(rpath(fs_ctx, path), stbuf);
35 if (err) {
36 return err;
37 }
38 if (fs_ctx->fs_sm == SM_MAPPED) {
39 /* Actual credentials are part of extended attrs */
40 uid_t tmp_uid;
41 gid_t tmp_gid;
42 mode_t tmp_mode;
43 dev_t tmp_dev;
44 if (getxattr(rpath(fs_ctx, path), "user.virtfs.uid", &tmp_uid,
45 sizeof(uid_t)) > 0) {
46 stbuf->st_uid = tmp_uid;
47 }
48 if (getxattr(rpath(fs_ctx, path), "user.virtfs.gid", &tmp_gid,
49 sizeof(gid_t)) > 0) {
50 stbuf->st_gid = tmp_gid;
51 }
52 if (getxattr(rpath(fs_ctx, path), "user.virtfs.mode", &tmp_mode,
53 sizeof(mode_t)) > 0) {
54 stbuf->st_mode = tmp_mode;
55 }
56 if (getxattr(rpath(fs_ctx, path), "user.virtfs.rdev", &tmp_dev,
57 sizeof(dev_t)) > 0) {
58 stbuf->st_rdev = tmp_dev;
59 }
60 }
61 return err;
131dcb25
AL
62}
63
758e8e38 64static int local_set_xattr(const char *path, FsCred *credp)
131dcb25 65{
758e8e38
VJ
66 int err;
67 if (credp->fc_uid != -1) {
68 err = setxattr(path, "user.virtfs.uid", &credp->fc_uid, sizeof(uid_t),
69 0);
70 if (err) {
71 return err;
72 }
131dcb25 73 }
758e8e38
VJ
74 if (credp->fc_gid != -1) {
75 err = setxattr(path, "user.virtfs.gid", &credp->fc_gid, sizeof(gid_t),
76 0);
77 if (err) {
78 return err;
79 }
131dcb25 80 }
758e8e38
VJ
81 if (credp->fc_mode != -1) {
82 err = setxattr(path, "user.virtfs.mode", &credp->fc_mode,
83 sizeof(mode_t), 0);
84 if (err) {
85 return err;
86 }
131dcb25 87 }
758e8e38
VJ
88 if (credp->fc_rdev != -1) {
89 err = setxattr(path, "user.virtfs.rdev", &credp->fc_rdev,
90 sizeof(dev_t), 0);
91 if (err) {
92 return err;
93 }
131dcb25 94 }
131dcb25
AL
95 return 0;
96}
97
98static ssize_t local_readlink(FsContext *ctx, const char *path,
99 char *buf, size_t bufsz)
100{
101 return readlink(rpath(ctx, path), buf, bufsz);
102}
103
104static int local_close(FsContext *ctx, int fd)
105{
106 return close(fd);
107}
108
109static int local_closedir(FsContext *ctx, DIR *dir)
110{
111 return closedir(dir);
112}
9f107513 113
a6568fe2
AL
114static int local_open(FsContext *ctx, const char *path, int flags)
115{
116 return open(rpath(ctx, path), flags);
117}
118
119static DIR *local_opendir(FsContext *ctx, const char *path)
120{
121 return opendir(rpath(ctx, path));
122}
123
a9231555
AL
124static void local_rewinddir(FsContext *ctx, DIR *dir)
125{
126 return rewinddir(dir);
127}
128
129static off_t local_telldir(FsContext *ctx, DIR *dir)
130{
131 return telldir(dir);
132}
133
134static struct dirent *local_readdir(FsContext *ctx, DIR *dir)
135{
136 return readdir(dir);
137}
138
139static void local_seekdir(FsContext *ctx, DIR *dir, off_t off)
140{
141 return seekdir(dir, off);
142}
143
144static ssize_t local_readv(FsContext *ctx, int fd, const struct iovec *iov,
145 int iovcnt)
146{
147 return readv(fd, iov, iovcnt);
148}
149
150static off_t local_lseek(FsContext *ctx, int fd, off_t offset, int whence)
151{
152 return lseek(fd, offset, whence);
153}
154
8449360c
AL
155static ssize_t local_writev(FsContext *ctx, int fd, const struct iovec *iov,
156 int iovcnt)
157{
158 return writev(fd, iov, iovcnt);
159}
160
e95ead32 161static int local_chmod(FsContext *fs_ctx, const char *path, FsCred *credp)
c494dd6f 162{
e95ead32
VJ
163 if (fs_ctx->fs_sm == SM_MAPPED) {
164 return local_set_xattr(rpath(fs_ctx, path), credp);
165 } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
166 return chmod(rpath(fs_ctx, path), credp->fc_mode);
167 }
168 return -1;
c494dd6f
AL
169}
170
171static int local_mknod(FsContext *ctx, const char *path, mode_t mode, dev_t dev)
172{
173 return mknod(rpath(ctx, path), mode, dev);
174}
175
176static int local_mksock(FsContext *ctx2, const char *path)
177{
178 struct sockaddr_un addr;
179 int s;
180
181 addr.sun_family = AF_UNIX;
182 snprintf(addr.sun_path, 108, "%s", rpath(ctx2, path));
183
184 s = socket(PF_UNIX, SOCK_STREAM, 0);
185 if (s == -1) {
186 return -1;
187 }
188
189 if (bind(s, (struct sockaddr *)&addr, sizeof(addr))) {
190 close(s);
191 return -1;
192 }
193
194 close(s);
195 return 0;
196}
197
198static int local_mkdir(FsContext *ctx, const char *path, mode_t mode)
199{
200 return mkdir(rpath(ctx, path), mode);
201}
202
1237ad76 203static int local_fstat(FsContext *fs_ctx, int fd, struct stat *stbuf)
c494dd6f 204{
1237ad76
VJ
205 int err;
206 err = fstat(fd, stbuf);
207 if (err) {
208 return err;
209 }
210 if (fs_ctx->fs_sm == SM_MAPPED) {
211 /* Actual credentials are part of extended attrs */
212 uid_t tmp_uid;
213 gid_t tmp_gid;
214 mode_t tmp_mode;
215 dev_t tmp_dev;
216
217 if (fgetxattr(fd, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) {
218 stbuf->st_uid = tmp_uid;
219 }
220 if (fgetxattr(fd, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) {
221 stbuf->st_gid = tmp_gid;
222 }
223 if (fgetxattr(fd, "user.virtfs.mode", &tmp_mode, sizeof(mode_t)) > 0) {
224 stbuf->st_mode = tmp_mode;
225 }
226 if (fgetxattr(fd, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) {
227 stbuf->st_rdev = tmp_dev;
228 }
229 }
230 return err;
c494dd6f
AL
231}
232
233static int local_open2(FsContext *ctx, const char *path, int flags, mode_t mode)
234{
235 return open(rpath(ctx, path), flags, mode);
236}
237
758e8e38 238
c494dd6f
AL
239static int local_symlink(FsContext *ctx, const char *oldpath,
240 const char *newpath)
241{
242 return symlink(oldpath, rpath(ctx, newpath));
243}
244
245static int local_link(FsContext *ctx, const char *oldpath, const char *newpath)
246{
247 char *tmp = qemu_strdup(rpath(ctx, oldpath));
248 int err, serrno = 0;
249
250 if (tmp == NULL) {
251 return -ENOMEM;
252 }
253
254 err = link(tmp, rpath(ctx, newpath));
255 if (err == -1) {
256 serrno = errno;
257 }
258
259 qemu_free(tmp);
260
261 if (err == -1) {
262 errno = serrno;
263 }
264
265 return err;
266}
267
8cf89e00
AL
268static int local_truncate(FsContext *ctx, const char *path, off_t size)
269{
270 return truncate(rpath(ctx, path), size);
271}
272
273static int local_rename(FsContext *ctx, const char *oldpath,
274 const char *newpath)
275{
276 char *tmp;
277 int err;
278
279 tmp = qemu_strdup(rpath(ctx, oldpath));
280 if (tmp == NULL) {
281 return -1;
282 }
283
284 err = rename(tmp, rpath(ctx, newpath));
285 if (err == -1) {
286 int serrno = errno;
287 qemu_free(tmp);
288 errno = serrno;
289 } else {
290 qemu_free(tmp);
291 }
292
293 return err;
294
295}
296
f7613bee 297static int local_chown(FsContext *fs_ctx, const char *path, FsCred *credp)
8cf89e00 298{
f7613bee
VJ
299 if (fs_ctx->fs_sm == SM_MAPPED) {
300 return local_set_xattr(rpath(fs_ctx, path), credp);
301 } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
302 return lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid);
303 }
304 return -1;
8cf89e00
AL
305}
306
307static int local_utime(FsContext *ctx, const char *path,
308 const struct utimbuf *buf)
309{
310 return utime(rpath(ctx, path), buf);
311}
312
5bae1900
AL
313static int local_remove(FsContext *ctx, const char *path)
314{
315 return remove(rpath(ctx, path));
316}
317
8cf89e00
AL
318static int local_fsync(FsContext *ctx, int fd)
319{
320 return fsync(fd);
321}
322
9f107513 323FileOperations local_ops = {
131dcb25 324 .lstat = local_lstat,
131dcb25
AL
325 .readlink = local_readlink,
326 .close = local_close,
327 .closedir = local_closedir,
a6568fe2
AL
328 .open = local_open,
329 .opendir = local_opendir,
a9231555
AL
330 .rewinddir = local_rewinddir,
331 .telldir = local_telldir,
332 .readdir = local_readdir,
333 .seekdir = local_seekdir,
334 .readv = local_readv,
335 .lseek = local_lseek,
8449360c 336 .writev = local_writev,
c494dd6f
AL
337 .chmod = local_chmod,
338 .mknod = local_mknod,
339 .mksock = local_mksock,
340 .mkdir = local_mkdir,
341 .fstat = local_fstat,
342 .open2 = local_open2,
343 .symlink = local_symlink,
344 .link = local_link,
8cf89e00
AL
345 .truncate = local_truncate,
346 .rename = local_rename,
347 .chown = local_chown,
348 .utime = local_utime,
5bae1900 349 .remove = local_remove,
8cf89e00 350 .fsync = local_fsync,
9f107513 351};