Skip to content

Commit 991f0ff

Browse files
authored
Add AF_UNIX sockets implementation (#11681)
* components/dfs: support unix socket nodes AF_UNIX pathname binding and descriptor passing require DFSv2 socket nodes and retained open file descriptions across fd tables. Add socket-node creation for tmpfs and devtmpfs, fd reference helpers, and socket F_SETFL forwarding. Impact: DFSv2 socket nodes and descriptor reference handling. Validation: git diff --cached --check. * components/net/sal: support local protocol providers Local IPC protocol families do not have a backing network device. Store the selected provider in each SAL socket and add a local provider registry while preserving netdev checks for Internet sockets. Handle DFSv2 close semantics, socketpair flags, and MSG_CTRUNC for AF_UNIX integration. Impact: SAL protocol dispatch for all socket families. Validation: git diff --cached --check. * components/lwp: support unix socket messages Musl AF_UNIX addresses and ancillary data require explicit ABI and user-memory conversion at the LWP syscall boundary. Add the musl msghdr layout, bounded address and message copying, control-message level conversion, and MSG_CTRUNC translation. Correct receive buffer allocation and copy lengths while handling messages. Impact: LWP socket syscalls when SAL is enabled. Validation: git diff --cached --check. * components/net/af_unix: add local sockets Add an opt-in AF_UNIX provider for pathname-based local IPC without a synthetic network device. Support datagram and stream sockets, blocking and nonblocking I/O, timeouts, poll, socketpair, and SCM_RIGHTS descriptor passing. Include bounded Kconfig settings, component documentation, and utest coverage. Impact: enabled only by RT_USING_AF_UNIX and requires SAL POSIX with DFSv2. Validation: git diff --cached --check. * Fix AF_UNIX CI checks Apply the repository clang-format rules to the affected source lines. Suppress the cppcheck false positive for the devtmpfs list iterator. No functional behavior is changed. * components/lwp: preserve NULL optional msghdr buffers When msg_name or msg_control is NULL, keep the kernel pointer NULL instead of substituting an uninitialized buffer. Reject a NULL control buffer with a nonzero length as EFAULT. Impact: LWP sendmsg/recvmsg conversion on MMU targets. Validation: git diff --cached --check. * components/net/af_unix: fix poll UAF, namespace leak, and SCM_RIGHTS cycles Poll only the local wait queue and wake writers from the receiver. Free namespace entries on detach, and reject AF_UNIX descriptors in SCM_RIGHTS until cycle collection exists. Impact: AF_UNIX poll, bind lifetime, and descriptor passing. Validation: git diff --cached --check. * components/dfs: add DFSv2 AF_UNIX utest suite Add opt-in tests under dfs/utest/v2/af_unix for socket nodes, IPC, poll peer-close, namespace cleanup, and SCM_RIGHTS rejection. Sources are built only when RT_UTEST_TC_USING_DFS_V2_AF_UNIX and the selected test groups are enabled. Impact: DFS utest menu and build; no production AF_UNIX behavior change. Validation: git diff --cached --check.
1 parent d2acd75 commit 991f0ff

36 files changed

Lines changed: 5726 additions & 241 deletions

components/dfs/dfs_v2/filesystems/devfs/devtmpfs.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#define TMPFS_TYPE_FILE 0x00
2828
#define TMPFS_TYPE_DIR 0x01
2929
#define TMPFS_TYPE_DYN_DEV 0x02 /* dynamic device */
30+
#define TMPFS_TYPE_SOCKET 0x03
3031

3132
struct devtmpfs_sb;
3233

@@ -223,6 +224,7 @@ static struct devtmpfs_file *devtmpfs_file_lookup(struct devtmpfs_sb *superblock
223224
if (rt_strcmp(file->name, filename) == 0)
224225
{
225226
rt_spin_unlock(&superblock->lock);
227+
/* cppcheck-suppress uninitvar */
226228
return file;
227229
}
228230
}
@@ -325,6 +327,10 @@ static int devtmpfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_
325327
{
326328
d->d_type = DT_DIR;
327329
}
330+
if (n_file->type == TMPFS_TYPE_SOCKET)
331+
{
332+
d->d_type = DT_SOCK;
333+
}
328334

329335
d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
330336
rt_strncpy(d->d_name, n_file->name, DIRENT_NAME_MAX);
@@ -540,6 +546,14 @@ static struct dfs_vnode *devtmpfs_create_vnode(struct dfs_dentry *dentry, int ty
540546
vnode->mode &= ~S_IFMT;
541547
vnode->mode |= S_IFDIR;
542548
}
549+
else if (type == FT_SOCKET ||
550+
(type == FT_REGULAR && S_ISSOCK(mode)))
551+
{
552+
d_file->type = TMPFS_TYPE_SOCKET;
553+
vnode->type = FT_SOCKET;
554+
vnode->mode &= ~S_IFMT;
555+
vnode->mode |= S_IFSOCK;
556+
}
543557
else
544558
{
545559
d_file->type = TMPFS_TYPE_FILE;
@@ -585,6 +599,10 @@ static struct dfs_vnode *devtmpfs_lookup(struct dfs_dentry *dentry)
585599
{
586600
vnode->type = FT_DIRECTORY;
587601
}
602+
else if (d_file->type == TMPFS_TYPE_SOCKET)
603+
{
604+
vnode->type = FT_SOCKET;
605+
}
588606
else if (d_file->link)
589607
{
590608
vnode->type = FT_SYMLINK;

components/dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,10 @@ static int dfs_tmpfs_getdents(struct dfs_file *file,
535535
{
536536
d->d_type = DT_DIR;
537537
}
538+
if (n_file->type == TMPFS_TYPE_SOCKET)
539+
{
540+
d->d_type = DT_SOCK;
541+
}
538542
d->d_namlen = RT_NAME_MAX;
539543
d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
540544
rt_strncpy(d->d_name, n_file->name, TMPFS_NAME_MAX);
@@ -664,6 +668,11 @@ static struct dfs_vnode *_dfs_tmpfs_lookup(struct dfs_dentry *dentry)
664668
vnode->mode = S_IFDIR | (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
665669
vnode->type = FT_DIRECTORY;
666670
}
671+
else if (d_file->type == TMPFS_TYPE_SOCKET)
672+
{
673+
vnode->mode = S_IFSOCK | (S_IRWXU | S_IRWXG | S_IRWXO);
674+
vnode->type = FT_SOCKET;
675+
}
667676
else
668677
{
669678
vnode->mode = S_IFREG | (S_IRWXU | S_IRWXG | S_IRWXO);
@@ -750,6 +759,13 @@ static struct dfs_vnode *dfs_tmpfs_create_vnode(struct dfs_dentry *dentry, int t
750759
vnode->mode = S_IFDIR | (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
751760
vnode->type = FT_DIRECTORY;
752761
}
762+
else if (type == FT_SOCKET ||
763+
(type == FT_REGULAR && S_ISSOCK(mode)))
764+
{
765+
d_file->type = TMPFS_TYPE_SOCKET;
766+
vnode->mode = S_IFSOCK | (mode & (S_IRWXU | S_IRWXG | S_IRWXO));
767+
vnode->type = FT_SOCKET;
768+
}
753769
else
754770
{
755771
d_file->type = TMPFS_TYPE_FILE;

components/dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#define TMPFS_TYPE_FILE 0x00
2121
#define TMPFS_TYPE_DIR 0x01
22+
#define TMPFS_TYPE_SOCKET 0x02
2223

2324
struct tmpfs_sb;
2425

@@ -46,4 +47,3 @@ struct tmpfs_sb
4647
int dfs_tmpfs_init(void);
4748

4849
#endif
49-

components/dfs/dfs_v2/include/dfs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,12 @@ int fdt_fd_associate_file(struct dfs_fdtable *fdt, int fd, struct dfs_file *file
134134
struct dfs_file *fd_get(int fd);
135135
void fd_release(int fd);
136136

137+
/* Reference helpers used when an open file description crosses fd tables. */
138+
int dfs_file_get_refs(const int *fds, size_t count, struct dfs_file **files);
139+
/* Successful installation transfers the supplied references to the fd table. */
140+
int dfs_file_install_refs(struct dfs_file **files, size_t count, int *fds);
141+
void dfs_file_put_ref(struct dfs_file *file);
142+
137143
void fd_init(struct dfs_file *fd);
138144

139145
struct dfs_fdtable *dfs_fdtable_get(void);

components/dfs/dfs_v2/include/dfs_file.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ void dfs_file_init(struct dfs_file *file);
149149
void dfs_file_deinit(struct dfs_file *file);
150150

151151
int dfs_file_open(struct dfs_file *file, const char *path, int flags, mode_t mode);
152+
int dfs_file_mknod(const char *path, int type, mode_t mode);
152153
int dfs_file_close(struct dfs_file *file);
153154

154155
off_t dfs_file_get_fpos(struct dfs_file *file);

components/dfs/dfs_v2/src/dfs.c

Lines changed: 110 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -349,23 +349,29 @@ int fdt_fd_new(struct dfs_fdtable *fdt)
349349
*/
350350
void fdt_fd_release(struct dfs_fdtable *fdt, int fd)
351351
{
352-
if (fd < fdt->maxfd)
352+
if (fdt == RT_NULL || dfs_file_lock() != RT_EOK)
353+
{
354+
return;
355+
}
356+
357+
if (fd >= 0 && fd < (int)fdt->maxfd)
353358
{
354359
struct dfs_file *file;
355360

356361
file = fdt_get_file(fdt, fd);
357362

358-
if (file && file->ref_count == 1)
363+
if (file != RT_NULL && file->ref_count == 1)
359364
{
360365
dfs_file_destroy(file);
361366
}
362-
else
367+
else if (file != RT_NULL)
363368
{
364369
rt_atomic_sub(&(file->ref_count), 1);
365370
}
366371

367372
fdt->fds[fd] = RT_NULL;
368373
}
374+
dfs_file_unlock();
369375
}
370376

371377
/**
@@ -493,6 +499,106 @@ struct dfs_file *fd_get(int fd)
493499
return fdt_get_file(fdt, fd);
494500
}
495501

502+
int dfs_file_get_refs(const int *fds, size_t count, struct dfs_file **files)
503+
{
504+
size_t index;
505+
struct dfs_fdtable *fdt;
506+
507+
if ((count != 0 && (fds == RT_NULL || files == RT_NULL)) ||
508+
dfs_file_lock() != RT_EOK)
509+
{
510+
return -EINVAL;
511+
}
512+
513+
fdt = dfs_fdtable_get();
514+
for (index = 0; index < count; index++)
515+
{
516+
files[index] = fdt_get_file(fdt, fds[index]);
517+
if (files[index] == RT_NULL ||
518+
(files[index]->dentry == RT_NULL && files[index]->vnode == RT_NULL))
519+
{
520+
dfs_file_unlock();
521+
return -EBADF;
522+
}
523+
}
524+
525+
for (index = 0; index < count; index++)
526+
{
527+
rt_atomic_add(&files[index]->ref_count, 1);
528+
}
529+
dfs_file_unlock();
530+
return 0;
531+
}
532+
533+
int dfs_file_install_refs(struct dfs_file **files, size_t count, int *fds)
534+
{
535+
int fd;
536+
int startfd;
537+
size_t index;
538+
struct dfs_fdtable *fdt;
539+
540+
if ((count != 0 && (files == RT_NULL || fds == RT_NULL)) ||
541+
dfs_file_lock() != RT_EOK)
542+
{
543+
return -EINVAL;
544+
}
545+
546+
fdt = dfs_fdtable_get();
547+
startfd = (fdt == &_fdtab) ? DFS_STDIO_OFFSET : 0;
548+
for (index = 0; index < count; index++)
549+
{
550+
if (files[index] == RT_NULL || files[index]->magic != DFS_FD_MAGIC)
551+
{
552+
break;
553+
}
554+
555+
fd = _fdt_slot_alloc(fdt, startfd);
556+
if (fd < 0)
557+
{
558+
break;
559+
}
560+
fdt->fds[fd] = files[index];
561+
fds[index] = fd;
562+
}
563+
564+
if (index != count)
565+
{
566+
while (index > 0)
567+
{
568+
index--;
569+
fdt->fds[fds[index]] = RT_NULL;
570+
}
571+
dfs_file_unlock();
572+
return -EMFILE;
573+
}
574+
575+
dfs_file_unlock();
576+
return 0;
577+
}
578+
579+
void dfs_file_put_ref(struct dfs_file *file)
580+
{
581+
if (file == RT_NULL || dfs_file_lock() != RT_EOK)
582+
{
583+
return;
584+
}
585+
586+
if (file->magic == DFS_FD_MAGIC &&
587+
rt_atomic_load(&file->ref_count) > 0 &&
588+
dfs_file_close(file) == 0)
589+
{
590+
if (rt_atomic_load(&file->ref_count) == 1)
591+
{
592+
dfs_file_destroy(file);
593+
}
594+
else
595+
{
596+
rt_atomic_sub(&file->ref_count, 1);
597+
}
598+
}
599+
dfs_file_unlock();
600+
}
601+
496602
/**
497603
* This function will get the file descriptor table of current process.
498604
*/
@@ -1238,4 +1344,4 @@ MSH_CMD_EXPORT(dfs_dlog, dfs dlog on|off);
12381344
#endif
12391345

12401346
#endif
1241-
/** @} */
1347+
/** @} */

0 commit comments

Comments
 (0)