]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/rpc.lockd/kern.c
sys/{x86,amd64}: remove one of doubled ;s
[FreeBSD/FreeBSD.git] / usr.sbin / rpc.lockd / kern.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Berkeley Software Design Inc's name may not be used to endorse or
15  *    promote products derived from this software without specific prior
16  *    written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  *      from BSDI kern.c,v 1.2 1998/11/25 22:38:27 don Exp
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include <sys/param.h>
37 #include <sys/mount.h>
38 #include <sys/queue.h>
39 #include <sys/socket.h>
40 #include <sys/stat.h>
41
42 #include <netinet/in.h>
43 #include <arpa/inet.h>
44
45 #include <err.h>
46 #include <errno.h>
47 #include <fcntl.h>
48 #include <paths.h>
49 #include <pwd.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <syslog.h>
54 #include <unistd.h>
55 #include <netdb.h>
56
57 #include "nlm_prot.h"
58 #include <nfs/nfsproto.h>
59 #include <nfs/nfs_lock.h>
60
61 #include "lockd.h"
62 #include "lockd_lock.h"
63 #include <nfsclient/nfs.h>
64
65 #define DAEMON_USERNAME "daemon"
66
67 /* Lock request owner. */
68 typedef struct __owner {
69         pid_t    pid;                           /* Process ID. */
70         time_t   tod;                           /* Time-of-day. */
71 } OWNER;
72 static OWNER owner;
73
74 static char hostname[MAXHOSTNAMELEN + 1];       /* Hostname. */
75 static int devfd;
76
77 static void     client_cleanup(void);
78 static const char *from_addr(struct sockaddr *);
79 int     lock_request(LOCKD_MSG *);
80 static void     set_auth(CLIENT *cl, struct xucred *ucred);
81 void    show(LOCKD_MSG *);
82 int     test_request(LOCKD_MSG *);
83 int     unlock_request(LOCKD_MSG *);
84
85 static int
86 nfslockdans(int vers, struct lockd_ans *ansp)
87 {
88
89         ansp->la_vers = vers;
90         return (write(devfd, ansp, sizeof *ansp) <= 0);
91 }
92
93 /*
94  * will break because fifo needs to be repopened when EOF'd
95  */
96 #define lockd_seteuid(uid)      seteuid(uid)
97
98 #define d_calls (debug_level > 1)
99 #define d_args (debug_level > 2)
100
101 static const char *
102 from_addr(struct sockaddr *saddr)
103 {
104         static char inet_buf[INET6_ADDRSTRLEN];
105
106         if (getnameinfo(saddr, saddr->sa_len, inet_buf, sizeof(inet_buf),
107                         NULL, 0, NI_NUMERICHOST) == 0)
108                 return inet_buf;
109         return "???";
110 }
111
112 void
113 client_cleanup(void)
114 {
115         (void)lockd_seteuid(0);
116         exit(-1);
117 }
118
119 /*
120  * client_request --
121  *      Loop around messages from the kernel, forwarding them off to
122  *      NLM servers.
123  */
124 pid_t
125 client_request(void)
126 {
127         LOCKD_MSG msg;
128         int nr, ret;
129         pid_t child;
130         uid_t daemon_uid;
131         struct passwd *pw;
132
133         /* Open the dev . */
134         devfd = open(_PATH_DEV _PATH_NFSLCKDEV, O_RDWR | O_NONBLOCK);
135         if (devfd < 0) {
136                 syslog(LOG_ERR, "open: %s: %m", _PATH_NFSLCKDEV);
137                 goto err;
138         }
139
140         signal(SIGPIPE, SIG_IGN);
141
142         /*
143          * Create a separate process, the client code is really a separate
144          * daemon that shares a lot of code.
145          */
146         switch (child = fork()) {
147         case -1:
148                 err(1, "fork");
149         case 0:
150                 setproctitle("client");
151                 break;
152         default:
153                 setproctitle("server");
154                 return (child);
155         }
156
157         signal(SIGHUP, (sig_t)client_cleanup);
158         signal(SIGTERM, (sig_t)client_cleanup);
159
160         /* Setup. */
161         (void)time(&owner.tod);
162         owner.pid = getpid();
163         (void)gethostname(hostname, sizeof(hostname) - 1);
164
165         pw = getpwnam(DAEMON_USERNAME);
166         if (pw == NULL) {
167                 syslog(LOG_ERR, "getpwnam: %s: %m", DAEMON_USERNAME);
168                 goto err;
169         }
170         daemon_uid = pw->pw_uid;
171         /* drop our root privileges */
172         (void)lockd_seteuid(daemon_uid);
173
174         for (;;) {
175                 /* Read the fixed length message. */
176                 if ((nr = read(devfd, &msg, sizeof(msg))) == sizeof(msg)) {
177                         if (d_args)
178                                 show(&msg);
179
180                         if (msg.lm_version != LOCKD_MSG_VERSION) {
181                                 syslog(LOG_ERR,
182                                     "unknown msg type: %d", msg.lm_version);
183                         }
184                         /*
185                          * Send it to the NLM server and don't grant the lock
186                          * if we fail for any reason.
187                          */
188                         switch (msg.lm_fl.l_type) {
189                         case F_RDLCK:
190                         case F_WRLCK:
191                                 if (msg.lm_getlk)
192                                         ret = test_request(&msg);
193                                 else
194                                         ret = lock_request(&msg);
195                                 break;
196                         case F_UNLCK:
197                                 ret = unlock_request(&msg);
198                                 break;
199                         default:
200                                 ret = 1;
201                                 syslog(LOG_ERR,
202                                     "unknown lock type: %d", msg.lm_fl.l_type);
203                                 break;
204                         }
205                         if (ret) {
206                                 struct lockd_ans ans;
207
208                                 ans.la_msg_ident = msg.lm_msg_ident;
209                                 ans.la_errno = EHOSTUNREACH;
210
211                                 if (nfslockdans(LOCKD_ANS_VERSION, &ans)) {
212                                         syslog((errno == EPIPE ? LOG_INFO : 
213                                                 LOG_ERR), "process %lu: %m",
214                                                 (u_long)msg.lm_msg_ident.pid);
215                                 }
216                         }
217                 } else if (nr == -1) {
218                         if (errno != EAGAIN) {
219                                 syslog(LOG_ERR, "read: %s: %m", _PATH_NFSLCKDEV);
220                                 goto err;
221                         }
222                 } else if (nr != 0) {
223                         syslog(LOG_ERR,
224                             "%s: discard %d bytes", _PATH_NFSLCKDEV, nr);
225                 }
226         }
227
228         /* Reached only on error. */
229 err:
230         (void)lockd_seteuid(0);
231         _exit (1);
232 }
233
234 void
235 set_auth(CLIENT *cl, struct xucred *xucred)
236 {
237         int ngroups;
238
239         ngroups = xucred->cr_ngroups - 1;
240         if (ngroups > NGRPS)
241                 ngroups = NGRPS;
242         if (cl->cl_auth != NULL)
243                 cl->cl_auth->ah_ops->ah_destroy(cl->cl_auth);
244         cl->cl_auth = authunix_create(hostname,
245                         xucred->cr_uid,
246                         xucred->cr_groups[0],
247                         ngroups,
248                         &xucred->cr_groups[1]);
249 }
250
251
252 /*
253  * test_request --
254  *      Convert a lock LOCKD_MSG into an NLM request, and send it off.
255  */
256 int
257 test_request(LOCKD_MSG *msg)
258 {
259         CLIENT *cli;
260         struct timeval timeout = {0, 0};        /* No timeout, no response. */
261         char dummy;
262
263         if (d_calls)
264                 syslog(LOG_DEBUG, "test request: %s: %s to %s",
265                     msg->lm_nfsv3 ? "V4" : "V1/3",
266                     msg->lm_fl.l_type == F_WRLCK ? "write" : "read",
267                     from_addr((struct sockaddr *)&msg->lm_addr));
268
269         if (msg->lm_nfsv3) {
270                 struct nlm4_testargs arg4;
271
272                 arg4.cookie.n_bytes = (char *)&msg->lm_msg_ident;
273                 arg4.cookie.n_len = sizeof(msg->lm_msg_ident);
274                 arg4.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
275                 arg4.alock.caller_name = hostname;
276                 arg4.alock.fh.n_bytes = (char *)&msg->lm_fh;
277                 arg4.alock.fh.n_len = msg->lm_fh_len;
278                 arg4.alock.oh.n_bytes = (char *)&owner;
279                 arg4.alock.oh.n_len = sizeof(owner);
280                 arg4.alock.svid = msg->lm_msg_ident.pid;
281                 arg4.alock.l_offset = msg->lm_fl.l_start;
282                 arg4.alock.l_len = msg->lm_fl.l_len;
283
284                 if ((cli = get_client(
285                     (struct sockaddr *)&msg->lm_addr,
286                     NLM_VERS4)) == NULL)
287                         return (1);
288
289                 set_auth(cli, &msg->lm_cred);
290                 (void)clnt_call(cli, NLM_TEST_MSG,
291                     (xdrproc_t)xdr_nlm4_testargs, &arg4,
292                     (xdrproc_t)xdr_void, &dummy, timeout);
293         } else {
294                 struct nlm_testargs arg;
295
296                 arg.cookie.n_bytes = (char *)&msg->lm_msg_ident;
297                 arg.cookie.n_len = sizeof(msg->lm_msg_ident);
298                 arg.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
299                 arg.alock.caller_name = hostname;
300                 arg.alock.fh.n_bytes = (char *)&msg->lm_fh;
301                 arg.alock.fh.n_len = msg->lm_fh_len;
302                 arg.alock.oh.n_bytes = (char *)&owner;
303                 arg.alock.oh.n_len = sizeof(owner);
304                 arg.alock.svid = msg->lm_msg_ident.pid;
305                 arg.alock.l_offset = msg->lm_fl.l_start;
306                 arg.alock.l_len = msg->lm_fl.l_len;
307
308                 if ((cli = get_client(
309                     (struct sockaddr *)&msg->lm_addr,
310                     NLM_VERS)) == NULL)
311                         return (1);
312
313                 set_auth(cli, &msg->lm_cred);
314                 (void)clnt_call(cli, NLM_TEST_MSG,
315                     (xdrproc_t)xdr_nlm_testargs, &arg,
316                     (xdrproc_t)xdr_void, &dummy, timeout);
317         }
318         return (0);
319 }
320
321 /*
322  * lock_request --
323  *      Convert a lock LOCKD_MSG into an NLM request, and send it off.
324  */
325 int
326 lock_request(LOCKD_MSG *msg)
327 {
328         CLIENT *cli;
329         struct nlm4_lockargs arg4;
330         struct nlm_lockargs arg;
331         struct timeval timeout = {0, 0};        /* No timeout, no response. */
332         char dummy;
333
334         if (d_calls)
335                 syslog(LOG_DEBUG, "lock request: %s: %s to %s",
336                     msg->lm_nfsv3 ? "V4" : "V1/3",
337                     msg->lm_fl.l_type == F_WRLCK ? "write" : "read",
338                     from_addr((struct sockaddr *)&msg->lm_addr));
339
340         if (msg->lm_nfsv3) {
341                 arg4.cookie.n_bytes = (char *)&msg->lm_msg_ident;
342                 arg4.cookie.n_len = sizeof(msg->lm_msg_ident);
343                 arg4.block = msg->lm_wait ? 1 : 0;
344                 arg4.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
345                 arg4.alock.caller_name = hostname;
346                 arg4.alock.fh.n_bytes = (char *)&msg->lm_fh;
347                 arg4.alock.fh.n_len = msg->lm_fh_len;
348                 arg4.alock.oh.n_bytes = (char *)&owner;
349                 arg4.alock.oh.n_len = sizeof(owner);
350                 arg4.alock.svid = msg->lm_msg_ident.pid;
351                 arg4.alock.l_offset = msg->lm_fl.l_start;
352                 arg4.alock.l_len = msg->lm_fl.l_len;
353                 arg4.reclaim = 0;
354                 arg4.state = nsm_state;
355
356                 if ((cli = get_client(
357                     (struct sockaddr *)&msg->lm_addr,
358                     NLM_VERS4)) == NULL)
359                         return (1);
360
361                 set_auth(cli, &msg->lm_cred);
362                 (void)clnt_call(cli, NLM_LOCK_MSG,
363                     (xdrproc_t)xdr_nlm4_lockargs, &arg4,
364                     (xdrproc_t)xdr_void, &dummy, timeout);
365         } else {
366                 arg.cookie.n_bytes = (char *)&msg->lm_msg_ident;
367                 arg.cookie.n_len = sizeof(msg->lm_msg_ident);
368                 arg.block = msg->lm_wait ? 1 : 0;
369                 arg.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
370                 arg.alock.caller_name = hostname;
371                 arg.alock.fh.n_bytes = (char *)&msg->lm_fh;
372                 arg.alock.fh.n_len = msg->lm_fh_len;
373                 arg.alock.oh.n_bytes = (char *)&owner;
374                 arg.alock.oh.n_len = sizeof(owner);
375                 arg.alock.svid = msg->lm_msg_ident.pid;
376                 arg.alock.l_offset = msg->lm_fl.l_start;
377                 arg.alock.l_len = msg->lm_fl.l_len;
378                 arg.reclaim = 0;
379                 arg.state = nsm_state;
380
381                 if ((cli = get_client(
382                     (struct sockaddr *)&msg->lm_addr,
383                     NLM_VERS)) == NULL)
384                         return (1);
385
386                 set_auth(cli, &msg->lm_cred);
387                 (void)clnt_call(cli, NLM_LOCK_MSG,
388                     (xdrproc_t)xdr_nlm_lockargs, &arg,
389                     (xdrproc_t)xdr_void, &dummy, timeout);
390         }
391         return (0);
392 }
393
394 /*
395  * unlock_request --
396  *      Convert an unlock LOCKD_MSG into an NLM request, and send it off.
397  */
398 int
399 unlock_request(LOCKD_MSG *msg)
400 {
401         CLIENT *cli;
402         struct nlm4_unlockargs arg4;
403         struct nlm_unlockargs arg;
404         struct timeval timeout = {0, 0};        /* No timeout, no response. */
405         char dummy;
406
407         if (d_calls)
408                 syslog(LOG_DEBUG, "unlock request: %s: to %s",
409                     msg->lm_nfsv3 ? "V4" : "V1/3",
410                     from_addr((struct sockaddr *)&msg->lm_addr));
411
412         if (msg->lm_nfsv3) {
413                 arg4.cookie.n_bytes = (char *)&msg->lm_msg_ident;
414                 arg4.cookie.n_len = sizeof(msg->lm_msg_ident);
415                 arg4.alock.caller_name = hostname;
416                 arg4.alock.fh.n_bytes = (char *)&msg->lm_fh;
417                 arg4.alock.fh.n_len = msg->lm_fh_len;
418                 arg4.alock.oh.n_bytes = (char *)&owner;
419                 arg4.alock.oh.n_len = sizeof(owner);
420                 arg4.alock.svid = msg->lm_msg_ident.pid;
421                 arg4.alock.l_offset = msg->lm_fl.l_start;
422                 arg4.alock.l_len = msg->lm_fl.l_len;
423
424                 if ((cli = get_client(
425                     (struct sockaddr *)&msg->lm_addr,
426                     NLM_VERS4)) == NULL)
427                         return (1);
428
429                 set_auth(cli, &msg->lm_cred);
430                 (void)clnt_call(cli, NLM_UNLOCK_MSG,
431                     (xdrproc_t)xdr_nlm4_unlockargs, &arg4,
432                     (xdrproc_t)xdr_void, &dummy, timeout);
433         } else {
434                 arg.cookie.n_bytes = (char *)&msg->lm_msg_ident;
435                 arg.cookie.n_len = sizeof(msg->lm_msg_ident);
436                 arg.alock.caller_name = hostname;
437                 arg.alock.fh.n_bytes = (char *)&msg->lm_fh;
438                 arg.alock.fh.n_len = msg->lm_fh_len;
439                 arg.alock.oh.n_bytes = (char *)&owner;
440                 arg.alock.oh.n_len = sizeof(owner);
441                 arg.alock.svid = msg->lm_msg_ident.pid;
442                 arg.alock.l_offset = msg->lm_fl.l_start;
443                 arg.alock.l_len = msg->lm_fl.l_len;
444
445                 if ((cli = get_client(
446                     (struct sockaddr *)&msg->lm_addr,
447                     NLM_VERS)) == NULL)
448                         return (1);
449
450                 set_auth(cli, &msg->lm_cred);
451                 (void)clnt_call(cli, NLM_UNLOCK_MSG,
452                     (xdrproc_t)xdr_nlm_unlockargs, &arg,
453                     (xdrproc_t)xdr_void, &dummy, timeout);
454         }
455
456         return (0);
457 }
458
459 int
460 lock_answer(int pid, netobj *netcookie, int result, int *pid_p, int version)
461 {
462         struct lockd_ans ans;
463
464         if (netcookie->n_len != sizeof(ans.la_msg_ident)) {
465                 if (pid == -1) {        /* we're screwed */
466                         syslog(LOG_ERR, "inedible nlm cookie");
467                         return -1;
468                 }
469                 ans.la_msg_ident.pid = pid;
470                 ans.la_msg_ident.msg_seq = -1;
471         } else {
472                 memcpy(&ans.la_msg_ident, netcookie->n_bytes,
473                     sizeof(ans.la_msg_ident));
474         }
475
476         if (d_calls)
477                 syslog(LOG_DEBUG, "lock answer: pid %lu: %s %d",
478                     (unsigned long)ans.la_msg_ident.pid,
479                     version == NLM_VERS4 ? "nlmv4" : "nlmv3",
480                     result);
481
482         ans.la_set_getlk_pid = 0;
483         if (version == NLM_VERS4)
484                 switch (result) {
485                 case nlm4_granted:
486                         ans.la_errno = 0;
487                         break;
488                 default:
489                         ans.la_errno = EACCES;
490                         break;
491                 case nlm4_denied:
492                         if (pid_p == NULL)
493                                 ans.la_errno = EAGAIN;
494                         else {
495                                 /* this is an answer to a nlm_test msg */
496                                 ans.la_set_getlk_pid = 1;
497                                 ans.la_getlk_pid = *pid_p;
498                                 ans.la_errno = 0;
499                         }
500                         break;
501                 case nlm4_denied_nolocks:
502                         ans.la_errno = EAGAIN;
503                         break;
504                 case nlm4_blocked:
505                         return -1;
506                         /* NOTREACHED */
507                 case nlm4_denied_grace_period:
508                         ans.la_errno = EAGAIN;
509                         break;
510                 case nlm4_deadlck:
511                         ans.la_errno = EDEADLK;
512                         break;
513                 case nlm4_rofs:
514                         ans.la_errno = EROFS;
515                         break;
516                 case nlm4_stale_fh:
517                         ans.la_errno = ESTALE;
518                         break;
519                 case nlm4_fbig:
520                         ans.la_errno = EFBIG;
521                         break;
522                 case nlm4_failed:
523                         ans.la_errno = EACCES;
524                         break;
525                 }
526         else
527                 switch (result) {
528                 case nlm_granted:
529                         ans.la_errno = 0;
530                         break;
531                 default:
532                         ans.la_errno = EACCES;
533                         break;
534                 case nlm_denied:
535                         if (pid_p == NULL)
536                                 ans.la_errno = EAGAIN;
537                         else {
538                                 /* this is an answer to a nlm_test msg */
539                                 ans.la_set_getlk_pid = 1;
540                                 ans.la_getlk_pid = *pid_p;
541                                 ans.la_errno = 0;
542                         }
543                         break;
544                 case nlm_denied_nolocks:
545                         ans.la_errno = EAGAIN;
546                         break;
547                 case nlm_blocked:
548                         return -1;
549                         /* NOTREACHED */
550                 case nlm_denied_grace_period:
551                         ans.la_errno = EAGAIN;
552                         break;
553                 case nlm_deadlck:
554                         ans.la_errno = EDEADLK;
555                         break;
556                 }
557
558         if (nfslockdans(LOCKD_ANS_VERSION, &ans)) {
559                 syslog(((errno == EPIPE || errno == ESRCH) ? 
560                         LOG_INFO : LOG_ERR), 
561                         "process %lu: %m", (u_long)ans.la_msg_ident.pid);
562                 return -1;
563         }
564         return 0;
565 }
566
567 /*
568  * show --
569  *      Display the contents of a kernel LOCKD_MSG structure.
570  */
571 void
572 show(LOCKD_MSG *mp)
573 {
574         static char hex[] = "0123456789abcdef";
575         struct fid *fidp;
576         fsid_t *fsidp;
577         size_t len;
578         u_int8_t *p, *t, buf[NFS_SMALLFH*3+1];
579
580         syslog(LOG_DEBUG, "process ID: %lu\n", (long)mp->lm_msg_ident.pid);
581
582         fsidp = (fsid_t *)&mp->lm_fh;
583         fidp = (struct fid *)((u_int8_t *)&mp->lm_fh + sizeof(fsid_t));
584
585         for (t = buf, p = (u_int8_t *)mp->lm_fh,
586             len = mp->lm_fh_len;
587             len > 0; ++p, --len) {
588                 *t++ = '\\';
589                 *t++ = hex[(*p & 0xf0) >> 4];
590                 *t++ = hex[*p & 0x0f];
591         }
592         *t = '\0';
593
594         syslog(LOG_DEBUG, "fh_len %d, fh %s\n", (int)mp->lm_fh_len, buf);
595
596         /* Show flock structure. */
597         syslog(LOG_DEBUG, "start %llu; len %llu; pid %lu; type %d; whence %d\n",
598             (unsigned long long)mp->lm_fl.l_start,
599             (unsigned long long)mp->lm_fl.l_len, (u_long)mp->lm_fl.l_pid,
600             mp->lm_fl.l_type, mp->lm_fl.l_whence);
601
602         /* Show wait flag. */
603         syslog(LOG_DEBUG, "wait was %s\n", mp->lm_wait ? "set" : "not set");
604 }