]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/compat/linux/linux.c
linux(4): style: Eliminate dead 'break' after 'return'
[FreeBSD/FreeBSD.git] / sys / compat / linux / linux.c
1 /*-
2  * Copyright (c) 2015 Dmitry Chagin
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <opt_inet6.h>
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/conf.h>
35 #include <sys/ctype.h>
36 #include <sys/jail.h>
37 #include <sys/lock.h>
38 #include <sys/malloc.h>
39 #include <sys/signalvar.h>
40 #include <sys/socket.h>
41 #include <sys/socketvar.h>
42
43 #include <net/if.h>
44 #include <net/if_var.h>
45 #include <net/if_dl.h>
46 #include <net/if_types.h>
47
48 #include <sys/un.h>
49 #include <netinet/in.h>
50
51 #include <compat/linux/linux.h>
52 #include <compat/linux/linux_common.h>
53 #include <compat/linux/linux_util.h>
54
55 struct futex_list futex_list;
56 struct mtx futex_mtx;                   /* protects the futex list */
57
58 CTASSERT(LINUX_IFNAMSIZ == IFNAMSIZ);
59
60 static int bsd_to_linux_sigtbl[LINUX_SIGTBLSZ] = {
61         LINUX_SIGHUP,   /* SIGHUP */
62         LINUX_SIGINT,   /* SIGINT */
63         LINUX_SIGQUIT,  /* SIGQUIT */
64         LINUX_SIGILL,   /* SIGILL */
65         LINUX_SIGTRAP,  /* SIGTRAP */
66         LINUX_SIGABRT,  /* SIGABRT */
67         0,              /* SIGEMT */
68         LINUX_SIGFPE,   /* SIGFPE */
69         LINUX_SIGKILL,  /* SIGKILL */
70         LINUX_SIGBUS,   /* SIGBUS */
71         LINUX_SIGSEGV,  /* SIGSEGV */
72         LINUX_SIGSYS,   /* SIGSYS */
73         LINUX_SIGPIPE,  /* SIGPIPE */
74         LINUX_SIGALRM,  /* SIGALRM */
75         LINUX_SIGTERM,  /* SIGTERM */
76         LINUX_SIGURG,   /* SIGURG */
77         LINUX_SIGSTOP,  /* SIGSTOP */
78         LINUX_SIGTSTP,  /* SIGTSTP */
79         LINUX_SIGCONT,  /* SIGCONT */
80         LINUX_SIGCHLD,  /* SIGCHLD */
81         LINUX_SIGTTIN,  /* SIGTTIN */
82         LINUX_SIGTTOU,  /* SIGTTOU */
83         LINUX_SIGIO,    /* SIGIO */
84         LINUX_SIGXCPU,  /* SIGXCPU */
85         LINUX_SIGXFSZ,  /* SIGXFSZ */
86         LINUX_SIGVTALRM,/* SIGVTALRM */
87         LINUX_SIGPROF,  /* SIGPROF */
88         LINUX_SIGWINCH, /* SIGWINCH */
89         0,              /* SIGINFO */
90         LINUX_SIGUSR1,  /* SIGUSR1 */
91         LINUX_SIGUSR2   /* SIGUSR2 */
92 };
93
94 static int linux_to_bsd_sigtbl[LINUX_SIGTBLSZ] = {
95         SIGHUP,         /* LINUX_SIGHUP */
96         SIGINT,         /* LINUX_SIGINT */
97         SIGQUIT,        /* LINUX_SIGQUIT */
98         SIGILL,         /* LINUX_SIGILL */
99         SIGTRAP,        /* LINUX_SIGTRAP */
100         SIGABRT,        /* LINUX_SIGABRT */
101         SIGBUS,         /* LINUX_SIGBUS */
102         SIGFPE,         /* LINUX_SIGFPE */
103         SIGKILL,        /* LINUX_SIGKILL */
104         SIGUSR1,        /* LINUX_SIGUSR1 */
105         SIGSEGV,        /* LINUX_SIGSEGV */
106         SIGUSR2,        /* LINUX_SIGUSR2 */
107         SIGPIPE,        /* LINUX_SIGPIPE */
108         SIGALRM,        /* LINUX_SIGALRM */
109         SIGTERM,        /* LINUX_SIGTERM */
110         SIGBUS,         /* LINUX_SIGSTKFLT */
111         SIGCHLD,        /* LINUX_SIGCHLD */
112         SIGCONT,        /* LINUX_SIGCONT */
113         SIGSTOP,        /* LINUX_SIGSTOP */
114         SIGTSTP,        /* LINUX_SIGTSTP */
115         SIGTTIN,        /* LINUX_SIGTTIN */
116         SIGTTOU,        /* LINUX_SIGTTOU */
117         SIGURG,         /* LINUX_SIGURG */
118         SIGXCPU,        /* LINUX_SIGXCPU */
119         SIGXFSZ,        /* LINUX_SIGXFSZ */
120         SIGVTALRM,      /* LINUX_SIGVTALARM */
121         SIGPROF,        /* LINUX_SIGPROF */
122         SIGWINCH,       /* LINUX_SIGWINCH */
123         SIGIO,          /* LINUX_SIGIO */
124         /*
125          * FreeBSD does not have SIGPWR signal, map Linux SIGPWR signal
126          * to the first unused FreeBSD signal number. Since Linux supports
127          * signals from 1 to 64 we are ok here as our SIGRTMIN = 65.
128          */
129         SIGRTMIN,       /* LINUX_SIGPWR */
130         SIGSYS          /* LINUX_SIGSYS */
131 };
132
133 static struct cdev *dev_shm_cdev;
134 static struct cdevsw dev_shm_cdevsw = {
135      .d_version = D_VERSION,
136      .d_name    = "dev_shm",
137 };
138
139 /*
140  * Map Linux RT signals to the FreeBSD RT signals.
141  */
142 static inline int
143 linux_to_bsd_rt_signal(int sig)
144 {
145
146         return (SIGRTMIN + 1 + sig - LINUX_SIGRTMIN);
147 }
148
149 static inline int
150 bsd_to_linux_rt_signal(int sig)
151 {
152
153         return (sig - SIGRTMIN - 1 + LINUX_SIGRTMIN);
154 }
155
156 int
157 linux_to_bsd_signal(int sig)
158 {
159
160         KASSERT(sig > 0 && sig <= LINUX_SIGRTMAX, ("invalid Linux signal %d\n", sig));
161
162         if (sig < LINUX_SIGRTMIN)
163                 return (linux_to_bsd_sigtbl[_SIG_IDX(sig)]);
164
165         return (linux_to_bsd_rt_signal(sig));
166 }
167
168 int
169 bsd_to_linux_signal(int sig)
170 {
171
172         if (sig <= LINUX_SIGTBLSZ)
173                 return (bsd_to_linux_sigtbl[_SIG_IDX(sig)]);
174         if (sig == SIGRTMIN)
175                 return (LINUX_SIGPWR);
176
177         return (bsd_to_linux_rt_signal(sig));
178 }
179
180 int
181 linux_to_bsd_sigaltstack(int lsa)
182 {
183         int bsa = 0;
184
185         if (lsa & LINUX_SS_DISABLE)
186                 bsa |= SS_DISABLE;
187         /*
188          * Linux ignores SS_ONSTACK flag for ss
189          * parameter while FreeBSD prohibits it.
190          */
191         return (bsa);
192 }
193
194 int
195 bsd_to_linux_sigaltstack(int bsa)
196 {
197         int lsa = 0;
198
199         if (bsa & SS_DISABLE)
200                 lsa |= LINUX_SS_DISABLE;
201         if (bsa & SS_ONSTACK)
202                 lsa |= LINUX_SS_ONSTACK;
203         return (lsa);
204 }
205
206 void
207 linux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss)
208 {
209         int b, l;
210
211         SIGEMPTYSET(*bss);
212         for (l = 1; l <= LINUX_SIGRTMAX; l++) {
213                 if (LINUX_SIGISMEMBER(*lss, l)) {
214                         b = linux_to_bsd_signal(l);
215                         if (b)
216                                 SIGADDSET(*bss, b);
217                 }
218         }
219 }
220
221 void
222 bsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss)
223 {
224         int b, l;
225
226         LINUX_SIGEMPTYSET(*lss);
227         for (b = 1; b <= SIGRTMAX; b++) {
228                 if (SIGISMEMBER(*bss, b)) {
229                         l = bsd_to_linux_signal(b);
230                         if (l)
231                                 LINUX_SIGADDSET(*lss, l);
232                 }
233         }
234 }
235
236 /*
237  * Translate a Linux interface name to a FreeBSD interface name,
238  * and return the associated ifnet structure
239  * bsdname and lxname need to be least IFNAMSIZ bytes long, but
240  * can point to the same buffer.
241  */
242 struct ifnet *
243 ifname_linux_to_bsd(struct thread *td, const char *lxname, char *bsdname)
244 {
245         struct ifnet *ifp;
246         int len, unit;
247         char *ep;
248         int index;
249         bool is_eth, is_lo;
250
251         for (len = 0; len < LINUX_IFNAMSIZ; ++len)
252                 if (!isalpha(lxname[len]) || lxname[len] == '\0')
253                         break;
254         if (len == 0 || len == LINUX_IFNAMSIZ)
255                 return (NULL);
256         /* Linux loopback interface name is lo (not lo0) */
257         is_lo = (len == 2 && strncmp(lxname, "lo", len) == 0);
258         unit = (int)strtoul(lxname + len, &ep, 10);
259         if ((ep == NULL || ep == lxname + len || ep >= lxname + LINUX_IFNAMSIZ) &&
260             is_lo == 0)
261                 return (NULL);
262         index = 0;
263         is_eth = (len == 3 && strncmp(lxname, "eth", len) == 0);
264
265         CURVNET_SET(TD_TO_VNET(td));
266         IFNET_RLOCK();
267         CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
268                 /*
269                  * Allow Linux programs to use FreeBSD names. Don't presume
270                  * we never have an interface named "eth", so don't make
271                  * the test optional based on is_eth.
272                  */
273                 if (strncmp(ifp->if_xname, lxname, LINUX_IFNAMSIZ) == 0)
274                         break;
275                 if (is_eth && IFP_IS_ETH(ifp) && unit == index++)
276                         break;
277                 if (is_lo && IFP_IS_LOOP(ifp))
278                         break;
279         }
280         IFNET_RUNLOCK();
281         CURVNET_RESTORE();
282         if (ifp != NULL && bsdname != NULL)
283                 strlcpy(bsdname, ifp->if_xname, IFNAMSIZ);
284         return (ifp);
285 }
286
287 void
288 linux_ifflags(struct ifnet *ifp, short *flags)
289 {
290         unsigned short fl;
291
292         fl = (ifp->if_flags | ifp->if_drv_flags) & 0xffff;
293         *flags = 0;
294         if (fl & IFF_UP)
295                 *flags |= LINUX_IFF_UP;
296         if (fl & IFF_BROADCAST)
297                 *flags |= LINUX_IFF_BROADCAST;
298         if (fl & IFF_DEBUG)
299                 *flags |= LINUX_IFF_DEBUG;
300         if (fl & IFF_LOOPBACK)
301                 *flags |= LINUX_IFF_LOOPBACK;
302         if (fl & IFF_POINTOPOINT)
303                 *flags |= LINUX_IFF_POINTOPOINT;
304         if (fl & IFF_DRV_RUNNING)
305                 *flags |= LINUX_IFF_RUNNING;
306         if (fl & IFF_NOARP)
307                 *flags |= LINUX_IFF_NOARP;
308         if (fl & IFF_PROMISC)
309                 *flags |= LINUX_IFF_PROMISC;
310         if (fl & IFF_ALLMULTI)
311                 *flags |= LINUX_IFF_ALLMULTI;
312         if (fl & IFF_MULTICAST)
313                 *flags |= LINUX_IFF_MULTICAST;
314 }
315
316 int
317 linux_ifhwaddr(struct ifnet *ifp, struct l_sockaddr *lsa)
318 {
319         struct ifaddr *ifa;
320         struct sockaddr_dl *sdl;
321
322         if (IFP_IS_LOOP(ifp)) {
323                 bzero(lsa, sizeof(*lsa));
324                 lsa->sa_family = LINUX_ARPHRD_LOOPBACK;
325                 return (0);
326         }
327
328         if (!IFP_IS_ETH(ifp))
329                 return (ENOENT);
330
331         CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
332                 sdl = (struct sockaddr_dl*)ifa->ifa_addr;
333                 if (sdl != NULL && (sdl->sdl_family == AF_LINK) &&
334                     (sdl->sdl_type == IFT_ETHER)) {
335                         bzero(lsa, sizeof(*lsa));
336                         lsa->sa_family = LINUX_ARPHRD_ETHER;
337                         bcopy(LLADDR(sdl), lsa->sa_data, LINUX_IFHWADDRLEN);
338                         return (0);
339                 }
340         }
341
342         return (ENOENT);
343 }
344
345 int
346 linux_to_bsd_domain(int domain)
347 {
348
349         switch (domain) {
350         case LINUX_AF_UNSPEC:
351                 return (AF_UNSPEC);
352         case LINUX_AF_UNIX:
353                 return (AF_LOCAL);
354         case LINUX_AF_INET:
355                 return (AF_INET);
356         case LINUX_AF_INET6:
357                 return (AF_INET6);
358         case LINUX_AF_AX25:
359                 return (AF_CCITT);
360         case LINUX_AF_IPX:
361                 return (AF_IPX);
362         case LINUX_AF_APPLETALK:
363                 return (AF_APPLETALK);
364         }
365         return (-1);
366 }
367
368 int
369 bsd_to_linux_domain(int domain)
370 {
371
372         switch (domain) {
373         case AF_UNSPEC:
374                 return (LINUX_AF_UNSPEC);
375         case AF_LOCAL:
376                 return (LINUX_AF_UNIX);
377         case AF_INET:
378                 return (LINUX_AF_INET);
379         case AF_INET6:
380                 return (LINUX_AF_INET6);
381         case AF_CCITT:
382                 return (LINUX_AF_AX25);
383         case AF_IPX:
384                 return (LINUX_AF_IPX);
385         case AF_APPLETALK:
386                 return (LINUX_AF_APPLETALK);
387         }
388         return (-1);
389 }
390
391 /*
392  * Based on the fact that:
393  * 1. Native and Linux storage of struct sockaddr
394  * and struct sockaddr_in6 are equal.
395  * 2. On Linux sa_family is the first member of all struct sockaddr.
396  */
397 int
398 bsd_to_linux_sockaddr(const struct sockaddr *sa, struct l_sockaddr **lsa,
399     socklen_t len)
400 {
401         struct l_sockaddr *kosa;
402         int error, bdom;
403
404         *lsa = NULL;
405         if (len < 2 || len > UCHAR_MAX)
406                 return (EINVAL);
407
408         kosa = malloc(len, M_SONAME, M_WAITOK);
409         bcopy(sa, kosa, len);
410
411         bdom = bsd_to_linux_domain(sa->sa_family);
412         if (bdom == -1) {
413                 error = EAFNOSUPPORT;
414                 goto out;
415         }
416
417         kosa->sa_family = bdom;
418         *lsa = kosa;
419         return (0);
420
421 out:
422         free(kosa, M_SONAME);
423         return (error);
424 }
425
426 int
427 linux_to_bsd_sockaddr(const struct l_sockaddr *osa, struct sockaddr **sap,
428     socklen_t *len)
429 {
430         struct sockaddr *sa;
431         struct l_sockaddr *kosa;
432 #ifdef INET6
433         struct sockaddr_in6 *sin6;
434         bool  oldv6size;
435 #endif
436         char *name;
437         int salen, bdom, error, hdrlen, namelen;
438
439         if (*len < 2 || *len > UCHAR_MAX)
440                 return (EINVAL);
441
442         salen = *len;
443
444 #ifdef INET6
445         oldv6size = false;
446         /*
447          * Check for old (pre-RFC2553) sockaddr_in6. We may accept it
448          * if it's a v4-mapped address, so reserve the proper space
449          * for it.
450          */
451         if (salen == sizeof(struct sockaddr_in6) - sizeof(uint32_t)) {
452                 salen += sizeof(uint32_t);
453                 oldv6size = true;
454         }
455 #endif
456
457         kosa = malloc(salen, M_SONAME, M_WAITOK);
458
459         if ((error = copyin(osa, kosa, *len)))
460                 goto out;
461
462         bdom = linux_to_bsd_domain(kosa->sa_family);
463         if (bdom == -1) {
464                 error = EAFNOSUPPORT;
465                 goto out;
466         }
467
468 #ifdef INET6
469         /*
470          * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6,
471          * which lacks the scope id compared with RFC2553 one. If we detect
472          * the situation, reject the address and write a message to system log.
473          *
474          * Still accept addresses for which the scope id is not used.
475          */
476         if (oldv6size) {
477                 if (bdom == AF_INET6) {
478                         sin6 = (struct sockaddr_in6 *)kosa;
479                         if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ||
480                             (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) &&
481                              !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) &&
482                              !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) &&
483                              !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
484                              !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) {
485                                 sin6->sin6_scope_id = 0;
486                         } else {
487                                 linux_msg(curthread,
488                                     "obsolete pre-RFC2553 sockaddr_in6 rejected");
489                                 error = EINVAL;
490                                 goto out;
491                         }
492                 } else
493                         salen -= sizeof(uint32_t);
494         }
495 #endif
496         if (bdom == AF_INET) {
497                 if (salen < sizeof(struct sockaddr_in)) {
498                         error = EINVAL;
499                         goto out;
500                 }
501                 salen = sizeof(struct sockaddr_in);
502         }
503
504         if (bdom == AF_LOCAL && salen > sizeof(struct sockaddr_un)) {
505                 hdrlen = offsetof(struct sockaddr_un, sun_path);
506                 name = ((struct sockaddr_un *)kosa)->sun_path;
507                 if (*name == '\0') {
508                         /*
509                          * Linux abstract namespace starts with a NULL byte.
510                          * XXX We do not support abstract namespace yet.
511                          */
512                         namelen = strnlen(name + 1, salen - hdrlen - 1) + 1;
513                 } else
514                         namelen = strnlen(name, salen - hdrlen);
515                 salen = hdrlen + namelen;
516                 if (salen > sizeof(struct sockaddr_un)) {
517                         error = ENAMETOOLONG;
518                         goto out;
519                 }
520         }
521
522         sa = (struct sockaddr *)kosa;
523         sa->sa_family = bdom;
524         sa->sa_len = salen;
525
526         *sap = sa;
527         *len = salen;
528         return (0);
529
530 out:
531         free(kosa, M_SONAME);
532         return (error);
533 }
534
535 void
536 linux_dev_shm_create(void)
537 {
538         int error;
539
540         error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK, &dev_shm_cdev,
541             &dev_shm_cdevsw, NULL, UID_ROOT, GID_WHEEL, 0, "shm/.mountpoint");
542         if (error != 0) {
543                 printf("%s: failed to create device node, error %d\n",
544                     __func__, error);
545         }
546 }
547
548 void
549 linux_dev_shm_destroy(void)
550 {
551
552         destroy_dev(dev_shm_cdev);
553 }
554
555 int
556 bsd_to_linux_bits_(int value, struct bsd_to_linux_bitmap *bitmap,
557     size_t mapcnt, int no_value)
558 {
559         int bsd_mask, bsd_value, linux_mask, linux_value;
560         int linux_ret;
561         size_t i;
562         bool applied;
563
564         applied = false;
565         linux_ret = 0;
566         for (i = 0; i < mapcnt; ++i) {
567                 bsd_mask = bitmap[i].bsd_mask;
568                 bsd_value = bitmap[i].bsd_value;
569                 if (bsd_mask == 0)
570                         bsd_mask = bsd_value;
571
572                 linux_mask = bitmap[i].linux_mask;
573                 linux_value = bitmap[i].linux_value;
574                 if (linux_mask == 0)
575                         linux_mask = linux_value;
576
577                 /*
578                  * If a mask larger than just the value is set, we explicitly
579                  * want to make sure that only this bit we mapped within that
580                  * mask is set.
581                  */
582                 if ((value & bsd_mask) == bsd_value) {
583                         linux_ret = (linux_ret & ~linux_mask) | linux_value;
584                         applied = true;
585                 }
586         }
587
588         if (!applied)
589                 return (no_value);
590         return (linux_ret);
591 }
592
593 int
594 linux_to_bsd_bits_(int value, struct bsd_to_linux_bitmap *bitmap,
595     size_t mapcnt, int no_value)
596 {
597         int bsd_mask, bsd_value, linux_mask, linux_value;
598         int bsd_ret;
599         size_t i;
600         bool applied;
601
602         applied = false;
603         bsd_ret = 0;
604         for (i = 0; i < mapcnt; ++i) {
605                 bsd_mask = bitmap[i].bsd_mask;
606                 bsd_value = bitmap[i].bsd_value;
607                 if (bsd_mask == 0)
608                         bsd_mask = bsd_value;
609
610                 linux_mask = bitmap[i].linux_mask;
611                 linux_value = bitmap[i].linux_value;
612                 if (linux_mask == 0)
613                         linux_mask = linux_value;
614
615                 /*
616                  * If a mask larger than just the value is set, we explicitly
617                  * want to make sure that only this bit we mapped within that
618                  * mask is set.
619                  */
620                 if ((value & linux_mask) == linux_value) {
621                         bsd_ret = (bsd_ret & ~bsd_mask) | bsd_value;
622                         applied = true;
623                 }
624         }
625
626         if (!applied)
627                 return (no_value);
628         return (bsd_ret);
629 }