On Wed, Jul 25, 2012 at 09:34:02PM +0200, Frank Brodbeck wrote:

> Hi,
> 
> currently I am trying (just out of curiosity) to find a way to resolve a
> duid to a device name. For that matter I believe that looking at
> disk_map() in subr_disk.c is the right place.
> 
> As I am a complete C beginner I have a hard time to understand a
> particular block of code so I decided to copy that function into my own
> C code so I can easily track what's going on w/ gdb:
> 
> int
> main(void)
> {
>         struct disk *dk, *mdk;
>         struct disklist_head disklist;
>         u_char uid[8];
>         char *path, *mpath, part, c;
>         int i;
> 
>         path = "9c750dc043a2751f.i";
>         part = path[17];
> 
>         bzero(uid, sizeof(uid));
>         for (i = 0; i < 16; i++) {
>                 c = path[i];
>                 if (c >= '0' && c <= '9')
>                         c -= '0';
>                 else if (c >= 'a' && c <= 'f')
>                         c -= ('a' - 10);
>                 else
>                         errx("Invalid duid");
> 
>                 uid[i / 2] <<= 4;
>                 uid[i / 2] |= c & 0xf;
>         }
> 
>         mdk = NULL;
>         TAILQ_FOREACH(dk, &disklist, dk_link) {
>                if ((dk->dk_flags & DKF_LABELVALID) && dk->dk_label &&
>                     bcmp(dk->dk_label->d_uid, uid,
>                     sizeof(dk->dk_label->d_uid)) == 0) {
>                         if (mdk != NULL)
>                                 return -1;
>                         mdk = dk;
>                 }
>         }
>       return 0;
> }
> 
> If I run the program I get a segfault and w/ gdb I see:
> Program received signal SIGSEGV, Segmentation fault.
> bcmp (b1=0x1c7f88988, b2=0x7f7ffffbe830, length=8) at
> /usr/src/lib/libc/string/bcmp.c:51
> 
> Which I believe is caused by dk->dk_label->d_uid being inaccessible:
> 
> (gdb) print dk->dk_label
> $1 = (struct disklabel *) 0x1c7f88948
> 
> (gdb) print dk->dk_label->d_uid
> Cannot access memory at address 0x1c7f88988
> 
> In dev/diskmap.c I see copyinstr(9) before disk_map() and copyoutstr(9)
> after disk_map. Is this because dk->dk_label->d_uid is not accessible
> from userspace or am I talking complete BS here?

Userland prorams do not share memory or symbols with the kernel at all
that is a fundamental thing in Unix. Your code just references a bunch
of uninitialized vars. 

Chekc opendev(3) (source in src/lib/libutil/opendev.c) which is a
userland function to do the translation you want. Note it interfaces
with the kernel via ioctl(2), the actual work is done by the diskmap
device driver that calls disk_map(), all in kernel mode.

        -Otto

Reply via email to