Learning NameFS, MDB — Pt. II

Here is an important excerpt from Solaris Internals, present in both the old version and the new (up to Solaris 10):

Application code that creates a door to a function typically creates a file in the file system to which the door descriptor can be attached, using the standard open(2) and fattach(3c) APIs, to make the door more easily accessible to other processes. 

The fattach(3C) API has traditionally been used for STREAMS code, where it is desirable to associate a STREAM or STREAMS-based pipe with a file in the file system name space; to make the descriptor easily accessible to other processes on the system. The binding of object to file name has already been solved.

fattach(3C) is implemented with a pseudo file system called namefs, the name file system. namefs allows the mounting of filesystems on nondirectory mount points, as opposed to the traditional mounting of a filesystem that requires the selected mount point to be a directory file. Currently, fattach is the only client application of namefs; it calls the mount(2) system call, passing namefs as the file system and a pointer to a namefs file descriptor. The mount system call enter the VFS switch table through the VFS_MOUNT macro and enters the namefs mount code, nm_mount()

The most important points made:
.) fattach is the only client application of namefs
.) namefs allows mounting on files rather than directories. (but what does that mean.. Can I navigate it like I would a directory or… ?? what is this strange file system??
.) Can I pass any kind of file desciptor through a file this way?? Not just STREAMS or doors??

Before I go read up on fattach() and programmatically creating these namefs mount points, I want to catch up summarizing some of my mdb activity.

MDB
these are some cool commands:

> ::nm -n namefs
Value              Size               Type  Bind  Other Shndx    Name
0x0000000000000000|0x0000000000000000|NOTY |LOCL |0x0  |UNDEF   |
0x00000000780989f4|0x0000000000001274|FUNC |GLOB |0x0  |1       |_fini
0x00000000780989fc|0x0000000000000018|FUNC |GLOB |0x0  |1       |_info
0x00000000780989d4|0x0000000000001274|FUNC |GLOB |0x0  |1       |_init
0x0000000078041db8|0x0000000000000048|OBJT |GLOB |0x0  |3       |dummyvfsops
0x0000000078041e28|0x0000000000000018|OBJT |LOCL |0x0  |3       |modlfs
0x0000000078041e40|0x0000000000000040|OBJT |LOCL |0x0  |3       |modlinkage
0x000000007801fc70|0x0000000000000008|OBJT |GLOB |0x0  |ABS     |namedev
0x0000000078098128|0x0000000000000068|FUNC |GLOB |0x0  |1       |namefind
0x000000007801fc7c|0x0000000000000004|OBJT |GLOB |0x0  |ABS     |namefstype
0x00000000780988f0|0x00000000000000e4|FUNC |GLOB |0x0  |1       |nameinit
0x00000000780980a0|0x0000000000000028|FUNC |GLOB |0x0  |1       |nameinsert
0x000000007801fc78|0x0000000000000004|OBJT |GLOB |0x0  |ABS     |namenode_shift
0x00000000780980c8|0x0000000000000060|FUNC |GLOB |0x0  |1       |nameremove
0x000000007801fc80|0x00000000000000a0|OBJT |GLOB |0x0  |ABS     |namevfs
0x0000000078099080|0x00000000000000cc|FUNC |LOCL |0x0  |1       |nm_access
0x0000000078098c34|0x00000000000000d0|FUNC |LOCL |0x0  |1       |nm_close
0x000000007809914c|0x000000000000007c|FUNC |LOCL |0x0  |1       |nm_create
0x000000007809923c|0x0000000000000018|FUNC |LOCL |0x0  |1       |nm_fid
0x000000007801fd20|0x0000000000000200|OBJT |GLOB |0x0  |ABS     |nm_filevp_hash
0x00000000780991d0|0x000000000000001c|FUNC |LOCL |0x0  |1       |nm_fsync
0x0000000078098d9c|0x0000000000000088|FUNC |LOCL |0x0  |1       |nm_getattr
0x00000000780991ec|0x0000000000000050|FUNC |LOCL |0x0  |1       |nm_inactive
0x0000000078098d64|0x0000000000000038|FUNC |LOCL |0x0  |1       |nm_ioctl
0x00000000780991c8|0x0000000000000008|FUNC |LOCL |0x0  |1       |nm_link
0x00000000780982c8|0x00000000000003c4|FUNC |LOCL |0x0  |1       |nm_mount
0x0000000078098a14|0x0000000000000220|FUNC |GLOB |0x0  |1       |nm_open
0x00000000780992dc|0x0000000000000038|FUNC |LOCL |0x0  |1       |nm_poll
0x0000000078098d04|0x0000000000000030|FUNC |LOCL |0x0  |1       |nm_read
0x00000000780992a4|0x0000000000000038|FUNC |LOCL |0x0  |1       |nm_realvp
0x0000000078098800|0x0000000000000030|FUNC |LOCL |0x0  |1       |nm_root
0x0000000078099254|0x000000000000001c|FUNC |LOCL |0x0  |1       |nm_rwlock
0x0000000078099270|0x000000000000001c|FUNC |LOCL |0x0  |1       |nm_rwunlock
0x000000007809928c|0x0000000000000018|FUNC |LOCL |0x0  |1       |nm_seek
0x0000000078098e24|0x000000000000025c|FUNC |LOCL |0x0  |1       |nm_setattr
0x0000000078098830|0x0000000000000070|FUNC |LOCL |0x0  |1       |nm_statvfs
0x00000000780988a0|0x0000000000000050|FUNC |LOCL |0x0  |1       |nm_sync
0x0000000078098190|0x00000000000000e8|FUNC |LOCL |0x0  |1       |nm_umountall
0x000000007809868c|0x0000000000000174|FUNC |LOCL |0x0  |1       |nm_unmount
0x0000000078098278|0x0000000000000050|FUNC |GLOB |0x0  |1       |nm_unmountall
0x0000000078041e80|0x0000000000000158|OBJT |GLOB |0x0  |3       |nm_vnodeops
0x0000000078098d34|0x0000000000000030|FUNC |LOCL |0x0  |1       |nm_write
0x0000000078041d70|0x0000000000000048|OBJT |GLOB |0x0  |3       |nmvfsops
0x000000007801fc68|0x0000000000000008|OBJT |GLOB |0x0  |ABS     |ntable_lock
0x0000000078041e00|0x0000000000000028|OBJT |LOCL |0x0  |3       |vfw
> ::fsinfo
            VFSP TYP             DATA OPS              MOUNT
        10445550   2      30000130018 ufs_vfsops       /
     30000513868   5      300000856c8 prvfsops         /proc
     300005137c8  15      3000051f978 mntvfsops        /etc/mnttab
     30000513728  12                0 fdvfsops         ??
     30000513688   4      30000b58028 nmvfsops         /etc/sysevent/syseve...
     30000513548  11      30000b493c8 tmp_vfsops       /var/run
     300005135e8   4      30000c31318 nmvfsops         /etc/sysevent/devfsa...
     300005134a8   4      30000c30f58 nmvfsops         ??
     30000513408   4      30000c30e18 nmvfsops         /etc/sysevent/piclev...
     30000513368   4      30000c302d8 nmvfsops         ??
     30000513228  11      30000b495f8 tmp_vfsops       /tmp
     30000513188   4      300012d2920 nmvfsops         ??
     300005130e8   4      300012d2ba0 nmvfsops         ??
     30000513048   4      300012d26a0 nmvfsops         ??
     30000512fa8  18      3000051e6e8 auto_vfsops      /net
     30000512f08  18      3000051e638 auto_vfsops      /home
     30000512e68  18      3000051e588 auto_vfsops      /xfn
     30000512d28   4      30001438938 nmvfsops         ??
     30000512dc8   4      30001438bb8 nmvfsops         /etc/.name_service_doo
     30000512c88   4      30001438578 nmvfsops         /var/spool/lp/fifos/...
     30000512b48   7      300016ccc00 nfs_vfsops       ??
     300005128c8   4      30001438438 nmvfsops         ??
     30000512aa8  10      30000aabce0 lo_vfsops        ??/root_fnnode/home/...
     30000512be8   4      30001634308 nmvfsops         ??
> $<vfslist


                vfs 10445550        
root:
root:           next            op              vnodecovered
                30000513868     ufs_vfsops      0               
root+0x18:      flag            bsize           fstype
                20              8192            2               
root+0x24:      fsid            data            dev
                220000000000002 30000130018     8800000000      
root+0x40:      bcount          nsubmounts      list
                0               16              0               
root+0x58:      hash            
                30000512aa8     
root+0x60:      reflock
root+0x60:      sleepq          count           
                0               0               
root+0x6c:      count           
                0               


                vfs 30000513868     
0x30000513868:  next            op              vnodecovered
                300005137c8     prvfsops        300010c2d78     
0x30000513880:  flag            bsize           fstype
                0               512             5               
0x3000051388c:  fsid            data            dev
                40c000000000005 300000856c8     10300000000     
0x300005138a8:  bcount          nsubmounts      list
                4294967296      0               1ea300001ea3    
0x300005138c0:  hash            
                0               
0x300005138c8:  reflock
0x300005138c8:  sleepq          count           
                0               0               
0x300005138d4:  count           
                0               


                vfs 300005137c8     
0x300005137c8:  next            op              vnodecovered
                30000513728     mntvfsops       300010c2618     
0x300005137e0:  flag            bsize           fstype
                0               512             15              
0x300005137ec:  fsid            data            dev
                41800000000000f 3000051f978     10600000000     
0x30000513808:  bcount          nsubmounts      list
                4294967296      0               12bb000012bb    
0x30000513820:  hash            
                0               
0x30000513828:  reflock
0x30000513828:  sleepq          count           
                0               0               
0x30000513834:  count           
                0               


                vfs 30000513728     
0x30000513728:  next            op              vnodecovered
                30000513688     fdvfsops        30000b42fa8     
0x30000513740:  flag            bsize           fstype
                0               1024            12              
0x3000051374c:  fsid            data            dev
                41c00000000000c 0               10700000000     
0x30000513768:  bcount          nsubmounts      list
                4294967296      0               1c0700001c07    
0x30000513780:  hash            
                30000513548     
0x30000513788:  reflock
0x30000513788:  sleepq          count           
                0               0               
0x30000513794:  count           
                0               


                vfs 30000513688     
0x30000513688:  next            op              vnodecovered
                30000513548     nmvfsops        300008be280     
0x300005136a0:  flag            bsize           fstype
                42              1024            4               
0x300005136ac:  fsid            data            dev
                428000000000004 30000b58028     10a00000000     
0x300005136c8:  bcount          nsubmounts      list
                0               0               e0000000e00     
0x300005136e0:  hash            
                300005135e8     
0x300005136e8:  reflock
0x300005136e8:  sleepq          count           
                0               0               
0x300005136f4:  count           
                0  

I dunno if I’m getting somewhere with this:

int
fattach(int fildes, const char *path)
{
  struct namefd  namefdp;
 struct door_info dinfo;
 int s;

 /* Only STREAMS and doors allowed to be mounted */
 if ((s = isastream(fildes)) == 1 || _door_info(fildes, &dinfo) == 0) {
  namefdp.fd = fildes;
  return (mount((char *)NULL, path, MS_DATA|MS_NOMNTTAB,
                    (const char *)"namefs", (char *)&namefdp,
                    sizeof (struct namefd)));
 } else if (s == 0) {
  /* Not a STREAM */
  errno = EINVAL;
  return (-1);
 } else {
  /* errno already set */
  return (-1);
 }
}

*supposed* to be limited to DOORS and STREAMS, but this could easily be replicated into my own program which did not do the check above. I have this code because I obtained Solaris 2.8 source code from eMule.

Invisible Symlinks
And now I have created what I call invisible symlinks

#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <stropts.h>
#include <sys/vnode.h>
#include <sys/door.h>
#include <sys/fs/namenode.h>
#include <sys/mount.h>
#include <fcntl.h>

int myfattach(int fildes, const char *path)
{
  struct namefd  namefdp;

  namefdp.fd = fildes;
  return (mount((char *)NULL, path, MS_DATA|MS_NOMNTTAB,
                    (const char *)"namefs", (char *)&namefdp,
                    sizeof (struct namefd)));
}

main()
{
  int fd1, fd2,fd3;
  char path1[] = "/tmp/namefs/1";
  char path2[] = "/tmp/namefs/2";
  char path3[] = "/tmp/namefs/3";
  
  int s;

  fd1 = open (path1, O_RDWR|O_CREAT );
  fd2 = open (path2, O_RDWR|O_CREAT );
  //fd3 = open (path3, O_RDWR|O_CREAT );

  //close(fd2);

 
 
 /* Only STREAMS and doors allowed to be mounted */

  
  int r = myfattach(fd1, path2);
  printf ("1st mount  = %d\n", r);

  r = myfattach(fd2,path1);

  printf ("2nd mount  = %d\n", r);

  getchar();

  fdetach(path2);
  fdetach(path1);
}

Before running the code:

-bash-4.3$ pwd
/tmp/namefs
-bash-4.3$ ls -l
total 0
-bash-4.3$

After running the code up until getchar():

-bash-4.3$ ls -l
total 0
-rwx--s---   1 bazz            0 Oct 28 07:02 1
-rwx--s---   1 bazz            0 Oct 28 07:02 2
-bash-4.3$ echo '1' > 1
-bash-4.3$ ls -l
total 0
-rwx--s---   1 bazz            0 Oct 28 07:02 1
-rwx--s---   1 bazz            0 Oct 28 07:02 2
-bash-4.3$ echo '2' > 2
-bash-4.3$ cat 1
1
-bash-4.3$ cat 2
2

I am not sure why they are setGID.. A: They are just the normal access permissions of O_CREAT.. I tried it without do any fattach() stuff.. HOWEVER, the setGID bit stays in the normal test.. where it gets changed to x bit in the fattach example. A: This is because I did not explicity close() the fd’s. When I explicitly close them in both examples, the SetGID bit stays..
Note The absence of change in file size…

After closing down the program: fdetach()

-bash-4.3$ ls -l
total 16
-rwx--x---   1 bazz            2 Oct 28 07:02 1
-rwx--x---   1 bazz            2 Oct 28 07:02 2
-bash-4.3$ cat 1
2
-bash-4.3$ cat 2
1
-bash-4.3$

pretty cool huh…

/* By BAzz

This code bypasses the "Only STREAMS and doors allowed to be mounted"
as NameFS nodes thing. Kind of creates invisible symlinks :) 

*/


#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <stropts.h>
#include <sys/vnode.h>
#include <sys/door.h>
#include <sys/fs/namenode.h>
#include <sys/mount.h>
#include <fcntl.h>



int myfattach(int fildes, const char *path)
{
  struct namefd  namefdp;

  namefdp.fd = fildes;
  return (mount((char *)NULL, path, MS_DATA|MS_NOMNTTAB,
                    (const char *)"namefs", (char *)&namefdp,
                    sizeof (struct namefd)));
}

main()
{
  int fd1, fd2,fd3;
  char path1[] = "/tmp/namefs/1";
  char path2[] = "/tmp/namefs/2";
  char path3[] = "/tmp/namefs/3";
  
  int s;

  fd1 = open (path1, O_RDWR|O_CREAT );
  fd2 = open (path2, O_RDWR|O_CREAT );
  //fd3 = open (path3, O_RDWR|O_CREAT );

  //close(fd2);

 
 


  
  int r = myfattach(fd1, path2);
  printf ("1st mount  = %d\n", r);

  r = myfattach(fd2,path1);

  printf ("2nd mount  = %d\n", r);

  getchar();

  fdetach(path2);
  fdetach(path1);

  close (fd1); close(fd2);
}

Leave a Reply

Your email address will not be published. Required fields are marked *

*