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