hc
2023-11-06 15ade055295d13f95d49e3d99b09f3bbfb4a43e7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
nfs.c: Allow max sa.sun_path for a localdomain socket with the user nfs-server
 
There is a hard limit for the kernel of 108 characters for a
localdomain socket name.  To avoid problems with the user nfs
server it should maximize the number of characters by using
a relative path on the server side.
 
Previously the nfs-server used the absolute path name passed to
the sa.sunpath arg for binding the socket and this has caused
problems for both the X server and UST binaries which make
heavy use of named sockets with long names.
 
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
 
Upstream-Status: Submitted http://sourceforge.net/p/unfs3/bugs/5/
 
---
 nfs.c |   29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)
 
--- a/nfs.c
+++ b/nfs.c
@@ -672,6 +672,7 @@ SYMLINK3res *nfsproc3_symlink_3_svc(SYML
 }
 
 #ifndef WIN32
+static char pathbuf_tmp[NFS_MAXPATHLEN + NFS_MAXNAMLEN + 1];
 
 /*
  * create Unix socket
@@ -680,17 +681,41 @@ static int mksocket(const char *path, mo
 {
     int res, sock;
     struct sockaddr_un addr;
+    unsigned int len = strlen(path);
 
     sock = socket(PF_UNIX, SOCK_STREAM, 0);
-    addr.sun_family = AF_UNIX;
-    strcpy(addr.sun_path, path);
     res = sock;
     if (res != -1) {
+    addr.sun_family = AF_UNIX;
+    if (len < sizeof(addr.sun_path) -1) {
+        strcpy(addr.sun_path, path);
+    } else {
+        char *ptr;
+        res = -1;
+        if (len >= sizeof(path))
+        goto out;
+        strcpy(pathbuf_tmp, path);
+        ptr = strrchr(pathbuf_tmp,'/');
+        if (ptr) {
+        *ptr = '\0';
+        ptr++;
+        if (chdir(pathbuf_tmp))
+            goto out;
+        } else {
+        ptr = pathbuf_tmp;
+        }
+        if (strlen(ptr) >= sizeof(addr.sun_path))
+        goto out;
+        strcpy(addr.sun_path, ptr);
+    }
     umask(~mode);
     res =
         bind(sock, (struct sockaddr *) &addr,
          sizeof(addr.sun_family) + strlen(addr.sun_path));
     umask(0);
+out:
+    if (chdir("/"))
+        fprintf(stderr, "Internal failure to chdir /\n");
     close(sock);
     }
     return res;