int main(void) { char bogus_special_str[sizeof(void *) * 2 + sizeof("0x")]; char bogus_addr_str[sizeof(void *) * 2 + sizeof("0x")]; char unterminated_str[sizeof(void *) * 2 + sizeof("0x")]; long rc; struct fs_disk_quota *xdq = tail_alloc(sizeof(*xdq)); struct fs_quota_stat *xqstat = tail_alloc(sizeof(*xqstat)); struct fs_quota_statv *xqstatv = tail_alloc(sizeof(*xqstatv)); uint32_t *flags = tail_alloc(sizeof(*flags)); char *unterminated = tail_memdup(unterminated_data, sizeof(unterminated_data)); snprintf(bogus_special_str, sizeof(bogus_special_str), "%p", bogus_special); snprintf(bogus_addr_str, sizeof(bogus_addr_str), "%p", bogus_addr); snprintf(unterminated_str, sizeof(unterminated_str), "%p", unterminated); /* Q_XQUOTAON */ *flags = 0xdeadbeef; check_quota(CQF_ID_SKIP | CQF_ADDR_STR, ARG_STR(QCMD(Q_XQUOTAON, USRQUOTA)), ARG_STR("/dev/bogus/"), flags, "[XFS_QUOTA_UDQ_ACCT|XFS_QUOTA_UDQ_ENFD" "|XFS_QUOTA_GDQ_ACCT|XFS_QUOTA_GDQ_ENFD" "|XFS_QUOTA_PDQ_ENFD|0xdeadbec0]"); rc = syscall(__NR_quotactl, QCMD(Q_XQUOTAON, 0xfacefeed), bogus_dev, bogus_id, bogus_addr); printf("quotactl(QCMD(Q_XQUOTAON, %#x /* ???QUOTA */)" ", %s, %p) = %s\n", QCMD_TYPE(QCMD(Q_XQUOTAON, 0xfacefeed)), bogus_dev_str, bogus_addr, sprintrc(rc)); /* Q_XQUOTAOFF */ check_quota(CQF_ID_SKIP | CQF_ADDR_STR, ARG_STR(QCMD(Q_XQUOTAOFF, USRQUOTA)), bogus_special, bogus_special_str, bogus_addr, bogus_addr_str); check_quota(CQF_ID_SKIP | CQF_ADDR_STR, ARG_STR(QCMD(Q_XQUOTAOFF, GRPQUOTA)), ARG_STR("/dev/bogus/"), ARG_STR(NULL)); check_quota(CQF_ID_SKIP | CQF_ADDR_STR, QCMD(Q_XQUOTAOFF, 3), "QCMD(Q_XQUOTAOFF, 0x3 /* ???QUOTA */)", ARG_STR("/dev/bogus/"), flags, "[XFS_QUOTA_UDQ_ACCT|XFS_QUOTA_UDQ_ENFD" "|XFS_QUOTA_GDQ_ACCT|XFS_QUOTA_GDQ_ENFD" "|XFS_QUOTA_PDQ_ENFD|0xdeadbec0]"); /* Q_XGETQUOTA */ /* Trying our best to get successful result */ check_quota(CQF_ADDR_CB, ARG_STR(QCMD(Q_GETQUOTA, USRQUOTA)), ARG_STR("/dev/sda1"), getuid(), xdq, print_xdisk_quota, (intptr_t) 1); check_quota(CQF_ADDR_CB, ARG_STR(QCMD(Q_GETQUOTA, GRPQUOTA)), ARG_STR(NULL), -1, xdq, print_xdisk_quota, (intptr_t) 2); /* Q_XGETNEXTQUOTA */ check_quota(CQF_ADDR_CB, ARG_STR(QCMD(Q_XGETNEXTQUOTA, USRQUOTA)), ARG_STR("/dev/sda1"), 0, xdq, print_xdisk_quota, (intptr_t) 1); /* Q_XSETQLIM */ check_quota(CQF_NONE, ARG_STR(QCMD(Q_XSETQLIM, PRJQUOTA)), bogus_special, bogus_special_str, 0, bogus_addr); fill_memory_ex((char *) xdq, sizeof(*xdq), 0x8e); check_quota(CQF_ADDR_CB, ARG_STR(QCMD(Q_XSETQLIM, PRJQUOTA)), bogus_dev, bogus_dev_str, 3141592653U, xdq, print_xdisk_quota, (intptr_t) 0); /* Q_XGETQSTAT */ check_quota(CQF_ID_SKIP | CQF_ADDR_CB, ARG_STR(QCMD(Q_XGETQSTAT, USRQUOTA)), ARG_STR("/dev/sda1"), xqstat, print_xquota_stat, (intptr_t) 1); check_quota(CQF_ID_SKIP | CQF_ADDR_CB, ARG_STR(QCMD(Q_XGETQSTATV, PRJQUOTA)), unterminated, unterminated_str, xqstat + 1, print_xquota_stat, (intptr_t) 2); /* Q_XGETQSTATV */ check_quota(CQF_ID_SKIP | CQF_ADDR_CB, ARG_STR(QCMD(Q_XGETQSTAT, USRQUOTA)), ARG_STR("/dev/sda1"), xqstatv, print_xquota_statv, 1); check_quota(CQF_ID_SKIP | CQF_ADDR_CB, ARG_STR(QCMD(Q_XGETQSTATV, GRPQUOTA)), ARG_STR(NULL), xqstatv, print_xquota_statv, (intptr_t) 2); /* Q_XQUOTARM */ check_quota(CQF_ID_SKIP | CQF_ADDR_STR, ARG_STR(QCMD(Q_XQUOTARM, PRJQUOTA)), bogus_special, bogus_special_str, ARG_STR(NULL)); check_quota(CQF_ID_SKIP, ARG_STR(QCMD(Q_XQUOTARM, USRQUOTA)), unterminated, unterminated_str, flags + 1); *flags = 0xdeadbeef; check_quota(CQF_ID_SKIP | CQF_ADDR_STR, ARG_STR(QCMD(Q_XQUOTARM, GRPQUOTA)), ARG_STR(NULL), flags, "[XFS_USER_QUOTA|XFS_PROJ_QUOTA" "|XFS_GROUP_QUOTA|0xdeadbee8]"); /* Q_XQUOTASYNC */ check_quota(CQF_ID_SKIP | CQF_ADDR_SKIP, ARG_STR(QCMD(Q_XQUOTASYNC, USRQUOTA)), bogus_special, bogus_special_str); check_quota(CQF_ID_SKIP | CQF_ADDR_SKIP, QCMD(Q_XQUOTASYNC, 0xfff), "QCMD(Q_XQUOTASYNC, 0xff /* ???QUOTA */)", ARG_STR(NULL)); puts("+++ exited with 0 +++"); return 0; }
int backup_phase1_server_all(struct async *as, struct sdirs *sdirs, struct conf **confs) { int ret=-1; struct sbuf *sb=NULL; char *phase1tmp=NULL; struct asfd *asfd=as->asfd; struct manio *manio=NULL; enum protocol protocol=get_protocol(confs); struct cntr *cntr=get_cntr(confs); logp("Begin phase1 (file system scan)\n"); if(!(phase1tmp=get_tmp_filename(sdirs->phase1data)) || !(manio=manio_open_phase1(phase1tmp, comp_level(get_int(confs[OPT_COMPRESSION])), protocol)) || !(sb=sbuf_alloc(protocol))) goto error; while(1) { sbuf_free_content(sb); switch(sbuf_fill_from_net(sb, asfd, NULL, NULL, cntr)) { case 0: break; case 1: // Last thing the client sends is // 'backupphase2', and it wants an 'ok' reply. if(asfd->write_str(asfd, CMD_GEN, "ok") || send_msg_fzp(manio->fzp, CMD_GEN, "phase1end", strlen("phase1end"))) goto error; goto end; case -1: default: goto error; } if(write_status(CNTR_STATUS_SCANNING, sb->path.buf, cntr) || manio_write_sbuf(manio, sb)) goto error; cntr_add_phase1(cntr, sb->path.cmd, 0); if(sbuf_is_filedata(sb)) { cntr_add_val(cntr, CMD_BYTES_ESTIMATED, (uint64_t)sb->statp.st_size, 0); } } end: if(manio_close(&manio)) { logp("error closing %s in backup_phase1_server\n", phase1tmp); goto error; } if(check_quota(as, cntr, get_uint64_t(confs[OPT_HARD_QUOTA]), get_uint64_t(confs[OPT_SOFT_QUOTA]))) goto error; // Possible rename race condition is of no consequence here, because // the working directory will always get deleted if phase1 is not // complete. if(do_rename(phase1tmp, sdirs->phase1data)) goto error; //cntr_print(p1cntr, cntr, ACTION_BACKUP); logp("End phase1 (file system scan)\n"); ret=0; error: free_w(&phase1tmp); manio_close(&manio); sbuf_free(&sb); return ret; }