db-d2/primevul-codebert-embeddings huggingface dataset:
Commit message: None
CVE: CVE-2017-6497
CWE: CWE-476
Vulnerability description: An issue was discovered in ImageMagick 6.9.7. A specially crafted psd file could lead to a NULL pointer dereference (thus, a DoS).

Project: ImageMagick

static MagickBooleanType ReadPSDChannel(Image *image,
  const ImageInfo *image_info,const PSDInfo *psd_info,LayerInfo* layer_info,
  const size_t channel,const PSDCompressionType compression,
  ExceptionInfo *exception)
{
  Image
    *channel_image,
    *mask;

  MagickOffsetType
    offset;

  MagickBooleanType
    status;

  channel_image=image;
  mask=(Image *) NULL;
  if (layer_info->channel_info[channel].type < -1)
    {
      const char
        *option;
      /*
        Ignore mask that is not a user supplied layer mask, if the mask is
        disabled or if the flags have unsupported values.
      */
      option=GetImageOption(image_info,"psd:preserve-opacity-mask");
      if ((layer_info->channel_info[channel].type != -2) ||
          (layer_info->mask.flags > 2) || ((layer_info->mask.flags & 0x02) &&
           (IsStringTrue(option) == MagickFalse)))
      {
        SeekBlob(image,layer_info->channel_info[channel].size-2,SEEK_CUR);
        return(MagickTrue);
       }
       mask=CloneImage(image,layer_info->mask.page.width,
         layer_info->mask.page.height,MagickFalse,exception);
      if (mask != (Image *) NULL)
        {
          mask->matte=MagickFalse;
          channel_image=mask;
        }
     }
 
   offset=TellBlob(image);
  status=MagickTrue;
  switch(compression)
  {
    case Raw:
      status=ReadPSDChannelRaw(channel_image,psd_info->channels,
        layer_info->channel_info[channel].type,exception);
      break;
    case RLE:
      {
        MagickOffsetType
          *sizes;

        sizes=ReadPSDRLESizes(channel_image,psd_info,channel_image->rows);
        if (sizes == (MagickOffsetType *) NULL)
          ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
            image->filename);
        status=ReadPSDChannelRLE(channel_image,psd_info,
          layer_info->channel_info[channel].type,sizes,exception);
        sizes=(MagickOffsetType *) RelinquishMagickMemory(sizes);
      }
      break;
    case ZipWithPrediction:
    case ZipWithoutPrediction:
#ifdef MAGICKCORE_ZLIB_DELEGATE
      status=ReadPSDChannelZip(channel_image,layer_info->channels,
        layer_info->channel_info[channel].type,compression,
        layer_info->channel_info[channel].size-2,exception);
#else
      (void) ThrowMagickException(exception,GetMagickModule(),
          MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn",
            "'%s' (ZLIB)",image->filename);
#endif
      break;
    default:
      (void) ThrowMagickException(exception,GetMagickModule(),TypeWarning,
        "CompressionNotSupported","'%.20g'",(double) compression);
      break;
  }

  SeekBlob(image,offset+layer_info->channel_info[channel].size-2,SEEK_SET);
  if (status == MagickFalse)
    {
      if (mask != (Image *) NULL)
        DestroyImage(mask);
      ThrowBinaryException(CoderError,"UnableToDecompressImage",
        image->filename);
    }
  layer_info->mask.image=mask;
  return(status);
}
Commit message: Exit gracefully in case of corrupted filters (Closes issue #782)
CVE: CVE-2017-6430
CWE: CWE-125
Vulnerability description: The compile_tree function in ef_compiler.c in the Etterfilter utility in Ettercap 0.8.2 and earlier allows remote attackers to cause a denial of service (out-of-bounds read) via a crafted filter.

Project: ettercap
File: ef_compiler.c

size_t compile_tree(struct filter_op **fop)
{
   int i = 1;
    struct filter_op *array = NULL;
    struct unfold_elm *ue;
 
   // invalid file
   if (tree_root == NULL)
      return 0;
   
    fprintf(stdout, " Unfolding the meta-tree ");
    fflush(stdout);
     
   /* start the recursion on the tree */
   unfold_blk(&tree_root);

   fprintf(stdout, " done.\n\n");

   /* substitute the virtual labels with real offsets */
   labels_to_offsets();
   
   /* convert the tailq into an array */
   TAILQ_FOREACH(ue, &unfolded_tree, next) {

      /* label == 0 means a real instruction */
      if (ue->label == 0) {
         SAFE_REALLOC(array, i * sizeof(struct filter_op));
         memcpy(&array[i - 1], &ue->fop, sizeof(struct filter_op));
         i++;
      }
   }
   
   /* always append the exit function to a script */
   SAFE_REALLOC(array, i * sizeof(struct filter_op));
   array[i - 1].opcode = FOP_EXIT;
   
   /* return the pointer to the array */
   *fop = array;
   
   return (i);
}

Project: ettercap
File: ef_output.c

int write_output(void)
{
   int fd;
   struct filter_op *fop;
   struct filter_header fh;
   size_t ninst, i;
   u_char *data;

   /* conver the tree to an array of filter_op */
   ninst = compile_tree(&fop);

    if (fop == NULL)
       return -E_NOTHANDLED;
 
   if (ninst == 0)
      return -E_INVALID;

    /* create the file */
    fd = open(EF_GBL_OPTIONS->output_file, O_CREAT | O_RDWR | O_TRUNC | O_BINARY, 0644);
    ON_ERROR(fd, -1, "Can't create file %s", EF_GBL_OPTIONS->output_file);

   /* display the message */
   fprintf(stdout, " Writing output to \'%s\' ", EF_GBL_OPTIONS->output_file);
   fflush(stdout);
   
   /* compute the header */
   fh.magic = htons(EC_FILTER_MAGIC);
   strncpy(fh.version, EC_VERSION, sizeof(fh.version));
   fh.data = sizeof(fh);

   data = create_data_segment(&fh, fop, ninst);
   
   /* write the header */
   write(fd, &fh, sizeof(struct filter_header));

   /* write the data segment */
   write(fd, data, fh.code - fh.data);
   
   /* write the instructions */
   for (i = 0; i <= ninst; i++) {
      print_progress_bar(&fop[i]);
      write(fd, &fop[i], sizeof(struct filter_op));
   }

   close(fd);
   
   fprintf(stdout, " done.\n\n");
  
   fprintf(stdout, " -> Script encoded into %d instructions.\n\n", (int)(i - 1));
   
   return E_SUCCESS;
}
Commit message: irda: Fix lockdep annotations in hashbin_delete().

A nested lock depth was added to the hasbin_delete() code but it
doesn't actually work some well and results in tons of lockdep splats.

Fix the code instead to properly drop the lock around the operation
and just keep peeking the head of the hashbin queue.

Reported-by: Dmitry Vyukov <dvyukov@google.com>
Tested-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
CVE: CVE-2017-6348
CWE: CWE-200
Vulnerability description: The hashbin_delete function in net/irda/irqueue.c in the Linux kernel before 4.9.13 improperly manages lock dropping, which allows local users to cause a denial of service (deadlock) via crafted operations on IrDA devices.

Project: linux
File: irqueue.c

 int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
 {
 	irda_queue_t* queue;
	unsigned long flags = 0;
	int i;

	IRDA_ASSERT(hashbin != NULL, return -1;);
 	IRDA_ASSERT(hashbin->magic == HB_MAGIC, return -1;);
 
 	/* Synchronize */
	if (hashbin->hb_type & HB_LOCK)
		spin_lock_irqsave(&hashbin->hb_spinlock, flags);
 
 	/*
 	 *  Free the entries in the hashbin, TODO: use hashbin_clear when
 	 *  it has been shown to work
 	 */
 	for (i = 0; i < HASHBIN_SIZE; i ++ ) {
		while (1) {
			queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]);

			if (!queue)
				break;

			if (free_func) {
				if (hashbin->hb_type & HB_LOCK)
					spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
				free_func(queue);
				if (hashbin->hb_type & HB_LOCK)
					spin_lock_irqsave(&hashbin->hb_spinlock, flags);
			}
 		}
 	}
 
	/* Cleanup local data */
	hashbin->hb_current = NULL;
 	hashbin->magic = ~HB_MAGIC;
 
 	/* Release lock */
	if (hashbin->hb_type & HB_LOCK)
 		spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
 
 	/*
 	 *  Free the hashbin structure
	 */
	kfree(hashbin);

	return 0;
}
Commit message: ip: fix IP_CHECKSUM handling

The skbs processed by ip_cmsg_recv() are not guaranteed to
be linear e.g. when sending UDP packets over loopback with
MSGMORE.
Using csum_partial() on [potentially] the whole skb len
is dangerous; instead be on the safe side and use skb_checksum().

Thanks to syzkaller team to detect the issue and provide the
reproducer.

v1 -> v2:
 - move the variable declaration in a tighter scope

Fixes: ad6f939ab193 ("ip: Add offset parameter to ip_cmsg_recv")
Reported-by: Andrey Konovalov <andreyknvl@google.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
CVE: CVE-2017-6347
CWE: CWE-125
Vulnerability description: The ip_cmsg_recv_checksum function in net/ipv4/ip_sockglue.c in the Linux kernel before 4.10.1 has incorrect expectations about skb data layout, which allows local users to cause a denial of service (buffer over-read) or possibly have unspecified other impact via crafted system calls, as demonstrated by use of the MSG_MORE flag in conjunction with loopback UDP transmission.

Project: linux
File: ip_sockglue.c

static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb,
				  int tlen, int offset)
{
	__wsum csum = skb->csum;

 	if (skb->ip_summed != CHECKSUM_COMPLETE)
 		return;
 
	if (offset != 0) {
		int tend_off = skb_transport_offset(skb) + tlen;
		csum = csum_sub(csum, skb_checksum(skb, tend_off, offset, 0));
	}
 
 	put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &csum);
 }
Commit message: purple: Fix crash on ft requests from unknown contacts

Followup to 701ab81 (included in 3.5) which was a partial fix which only
improved things for non-libpurple file transfers (that is, just jabber)
CVE: CVE-2017-5668
CWE: CWE-476
Vulnerability description: bitlbee-libpurple before 3.5.1 allows remote attackers to cause a denial of service (NULL pointer dereference and crash) and possibly execute arbitrary code via a file transfer request for a contact that is not in the contact list.  NOTE: this vulnerability exists because of an incomplete fix for CVE-2016-10189.

Project: bitlbee

static gboolean prplcb_xfer_new_send_cb(gpointer data, gint fd, b_input_condition cond)
{
	PurpleXfer *xfer = data;
	struct im_connection *ic = purple_ic_by_pa(xfer->account);
	struct prpl_xfer_data *px = xfer->ui_data;
	PurpleBuddy *buddy;
	const char *who;

	buddy = purple_find_buddy(xfer->account, xfer->who);
	who = buddy ? purple_buddy_get_name(buddy) : xfer->who;

 	/* TODO(wilmer): After spreading some more const goodness in BitlBee,
 	   remove the evil cast below. */
 	px->ft = imcb_file_send_start(ic, (char *) who, xfer->filename, xfer->size);

	if (!px->ft) {
		return FALSE;
	}
 	px->ft->data = px;
 
 	px->ft->accept = prpl_xfer_accept;
	px->ft->canceled = prpl_xfer_canceled;
	px->ft->free = prpl_xfer_free;
	px->ft->write_request = prpl_xfer_write_request;

	return FALSE;
}
Commit message: tmpfs: clear S_ISGID when setting posix ACLs

This change was missed the tmpfs modification in In CVE-2016-7097
commit 073931017b49 ("posix_acl: Clear SGID bit when setting
file permissions")
It can test by xfstest generic/375, which failed to clear
setgid bit in the following test case on tmpfs:

  touch $testfile
  chown 100:100 $testfile
  chmod 2755 $testfile
  _runas -u 100 -g 101 -- setfacl -m u::rwx,g::rwx,o::rwx $testfile

Signed-off-by: Gu Zheng <guzheng1@huawei.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
CVE: CVE-2017-5551
CWE: CWE-284
Vulnerability description: The simple_set_acl function in fs/posix_acl.c in the Linux kernel before 4.9.6 preserves the setgid bit during a setxattr call involving a tmpfs filesystem, which allows local users to gain group privileges by leveraging the existence of a setgid program with restrictions on execute permissions.  NOTE: this vulnerability exists because of an incomplete fix for CVE-2016-7097.

Project: linux
File: posix_acl.c

int simple_set_acl(struct inode *inode, struct posix_acl *acl, int type)
{
 	int error;
 
 	if (type == ACL_TYPE_ACCESS) {
		error = posix_acl_update_mode(inode,
				&inode->i_mode, &acl);
		if (error)
			return error;
 	}
 
 	inode->i_ctime = current_time(inode);
	set_cached_acl(inode, type, acl);
	return 0;
}
Commit message: fix a fencepost error in pipe_advance()

The logics in pipe_advance() used to release all buffers past the new
position failed in cases when the number of buffers to release was equal
to pipe->buffers.  If that happened, none of them had been released,
leaving pipe full.  Worse, it was trivial to trigger and we end up with
pipe full of uninitialized pages.  IOW, it's an infoleak.

Cc: stable@vger.kernel.org # v4.9
Reported-by: "Alan J. Wylie" <alan@wylie.me.uk>
Tested-by: "Alan J. Wylie" <alan@wylie.me.uk>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
CVE: CVE-2017-5550
CWE: CWE-200
Vulnerability description: Off-by-one error in the pipe_advance function in lib/iov_iter.c in the Linux kernel before 4.9.5 allows local users to obtain sensitive information from uninitialized heap-memory locations in opportunistic circumstances by reading from a pipe after an incorrect buffer-release decision.

Project: linux
File: iov_iter.c

void iov_iter_pipe(struct iov_iter *i, int direction,
			struct pipe_inode_info *pipe,
 			size_t count)
 {
 	BUG_ON(direction != ITER_PIPE);
	WARN_ON(pipe->nrbufs == pipe->buffers);
 	i->type = direction;
 	i->pipe = pipe;
 	i->idx = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1);
	i->iov_offset = 0;
	i->count = count;
}

Project: linux
File: iov_iter.c

 static void pipe_advance(struct iov_iter *i, size_t size)
 {
 	struct pipe_inode_info *pipe = i->pipe;
 	if (unlikely(i->count < size))
 		size = i->count;
 	if (size) {
		struct pipe_buffer *buf;
		size_t off = i->iov_offset, left = size;
		int idx = i->idx;
 		if (off) /* make it relative to the beginning of buffer */
			left += off - pipe->bufs[idx].offset;
 		while (1) {
 			buf = &pipe->bufs[idx];
			if (left <= buf->len)
 				break;
			left -= buf->len;
 			idx = next_idx(idx, pipe);
 		}
 		i->idx = idx;
		i->iov_offset = buf->offset + left;
 	}
	i->count -= size;
	/* ... and discard everything past that point */
	pipe_truncate(i);
 }
Commit message: USB: serial: kl5kusb105: fix line-state error handling

The current implementation failed to detect short transfers when
attempting to read the line state, and also, to make things worse,
logged the content of the uninitialised heap transfer buffer.

Fixes: abf492e7b3ae ("USB: kl5kusb105: fix DMA buffers on stack")
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable <stable@vger.kernel.org>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
CVE: CVE-2017-5549
CWE: CWE-532
Vulnerability description: The klsi_105_get_line_state function in drivers/usb/serial/kl5kusb105.c in the Linux kernel before 4.9.5 places uninitialized heap-memory contents into a log entry upon a failure to read the line status, which allows local users to obtain sensitive information by reading the log.

Project: linux
File: kl5kusb105.c

static int klsi_105_get_line_state(struct usb_serial_port *port,
				   unsigned long *line_state_p)
{
	int rc;
	u8 *status_buf;
	__u16 status;

	dev_info(&port->serial->dev->dev, "sending SIO Poll request\n");

	status_buf = kmalloc(KLSI_STATUSBUF_LEN, GFP_KERNEL);
	if (!status_buf)
		return -ENOMEM;

	status_buf[0] = 0xff;
	status_buf[1] = 0xff;
	rc = usb_control_msg(port->serial->dev,
			     usb_rcvctrlpipe(port->serial->dev, 0),
			     KL5KUSB105A_SIO_POLL,
			     USB_TYPE_VENDOR | USB_DIR_IN,
			     0, /* value */
			     0, /* index */
 			     status_buf, KLSI_STATUSBUF_LEN,
 			     10000
 			     );
	if (rc != KLSI_STATUSBUF_LEN) {
		dev_err(&port->dev, "reading line status failed: %d\n", rc);
		if (rc >= 0)
			rc = -EIO;
	} else {
 		status = get_unaligned_le16(status_buf);
 
 		dev_info(&port->serial->dev->dev, "read status %x %x\n",
			 status_buf[0], status_buf[1]);

		*line_state_p = klsi_105_status2linestate(status);
	}

	kfree(status_buf);
	return rc;
}
Commit message: plistutil: Prevent OOB heap buffer read by checking input size

As pointed out in #87 plistutil would do a memcmp with a heap buffer
without checking the size. If the size is less than 8 it would read
beyond the bounds of this heap buffer. This commit prevents that.
CVE: CVE-2017-5545
CWE: CWE-125
Vulnerability description: The main function in plistutil.c in libimobiledevice libplist through 1.12 allows attackers to obtain sensitive information from process memory or cause a denial of service (buffer over-read) via Apple Property List data that is too short.

Project: libplist

int main(int argc, char *argv[])
{
    FILE *iplist = NULL;
    plist_t root_node = NULL;
    char *plist_out = NULL;
    uint32_t size = 0;
    int read_size = 0;
    char *plist_entire = NULL;
    struct stat filestats;
    options_t *options = parse_arguments(argc, argv);

    if (!options)
    {
        print_usage(argc, argv);
        return 0;
    }

    iplist = fopen(options->in_file, "rb");
    if (!iplist) {
        free(options);
        return 1;
     }
 
     stat(options->in_file, &filestats);

    if (filestats.st_size < 8) {
        printf("ERROR: Input file is too small to contain valid plist data.\n");
        return -1;
    }

     plist_entire = (char *) malloc(sizeof(char) * (filestats.st_size + 1));
     read_size = fread(plist_entire, sizeof(char), filestats.st_size, iplist);
     fclose(iplist);

    if (memcmp(plist_entire, "bplist00", 8) == 0)
    {
        plist_from_bin(plist_entire, read_size, &root_node);
        plist_to_xml(root_node, &plist_out, &size);
    }
    else
    {
        plist_from_xml(plist_entire, read_size, &root_node);
        plist_to_bin(root_node, &plist_out, &size);
    }
    plist_free(root_node);
    free(plist_entire);

    if (plist_out)
    {
        if (options->out_file != NULL)
        {
            FILE *oplist = fopen(options->out_file, "wb");
            if (!oplist) {
                free(options);
                return 1;
            }
            fwrite(plist_out, size, sizeof(char), oplist);
            fclose(oplist);
        }
        else
            fwrite(plist_out, size, sizeof(char), stdout);

        free(plist_out);
    }
    else
        printf("ERROR: Failed to convert input file.\n");

    free(options);
    return 0;
}
Commit message: Fix #73832 - leave the table in a safe state if the size is too big.
CVE: CVE-2017-5340
CWE: CWE-190
Vulnerability description: Zend/zend_hash.c in PHP before 7.0.15 and 7.1.x before 7.1.1 mishandles certain cases that require large array allocations, which allows remote attackers to execute arbitrary code or cause a denial of service (integer overflow, uninitialized memory access, and use of arbitrary destructor function pointers) via crafted serialized data.

Project: php-src
File: zend_hash.c

ZEND_API void ZEND_FASTCALL _zend_hash_init(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
{
 	GC_REFCOUNT(ht) = 1;
 	GC_TYPE_INFO(ht) = IS_ARRAY;
 	ht->u.flags = (persistent ? HASH_FLAG_PERSISTENT : 0) | HASH_FLAG_APPLY_PROTECTION | HASH_FLAG_STATIC_KEYS;
 	ht->nTableMask = HT_MIN_MASK;
 	HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
 	ht->nNumUsed = 0;
 	ht->nNumOfElements = 0;
 	ht->nInternalPointer = HT_INVALID_IDX;
 	ht->nNextFreeElement = 0;
 	ht->pDestructor = pDestructor;
	ht->nTableSize = zend_hash_check_size(nSize);
 }
Commit message: base64: Rework base64decode to handle split encoded data correctly
CVE: CVE-2017-5209
CWE: CWE-125
Vulnerability description: The base64decode function in base64.c in libimobiledevice libplist through 1.12 allows attackers to obtain sensitive information from process memory or cause a denial of service (buffer over-read) via split encoded Apple Property List data.

Project: libplist

 unsigned char *base64decode(const char *buf, size_t *size)
 {
 	if (!buf || !size) return NULL;
	size_t len = (*size > 0) ? *size : strlen(buf);
	if (len <= 0) return NULL;
 	unsigned char *outbuf = (unsigned char*)malloc((len/4)*3+3);
 	const char *ptr = buf;
 	int p = 0;
	int wv, w1, w2, w3, w4;
	int tmpval[4];
	int tmpcnt = 0;
 
 	do {
		while (ptr < buf+len && (*ptr == ' ' || *ptr == '\t' || *ptr == '\n' || *ptr == '\r')) {
			ptr++;
		}
 		if (*ptr == '\0' || ptr >= buf+len) {
 			break;
 		}
		if ((wv = base64_table[(int)(unsigned char)*ptr++]) == -1) {
			continue;
		}
		tmpval[tmpcnt++] = wv;
		if (tmpcnt == 4) {
			tmpcnt = 0;
			w1 = tmpval[0];
			w2 = tmpval[1];
			w3 = tmpval[2];
			w4 = tmpval[3];

			if (w2 >= 0) {
				outbuf[p++] = (unsigned char)(((w1 << 2) + (w2 >> 4)) & 0xFF);
			}
			if (w3 >= 0) {
				outbuf[p++] = (unsigned char)(((w2 << 4) + (w3 >> 2)) & 0xFF);
			}
			if (w4 >= 0) {
				outbuf[p++] = (unsigned char)(((w3 << 6) + w4) & 0xFF);
			}
 		}
 	} while (1);
 
	outbuf[p] = 0;
	*size = p;
	return outbuf;
}

Project: libplist

static int base64decode_block(unsigned char *target, const char *data, size_t data_size)
Commit message: security fix
CVE: CVE-2017-5207
CWE: CWE-269
Vulnerability description: Firejail before 0.9.44.4, when running a bandwidth command, allows local users to gain root privileges via the --shell argument.

Project: firejail

void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, int up) {
	EUID_ASSERT();
	EUID_ROOT();
	char *comm = pid_proc_comm(pid);
	EUID_USER();
	if (!comm) {
		fprintf(stderr, "Error: cannot find sandbox\n");
		exit(1);
	}

	if (strcmp(comm, "firejail") != 0) {
		fprintf(stderr, "Error: cannot find sandbox\n");
		exit(1);
	}
	free(comm);
	
	char *name;
	if (asprintf(&name, "/run/firejail/network/%d-netmap", pid) == -1)
		errExit("asprintf");
	struct stat s;
	if (stat(name, &s) == -1) {
		fprintf(stderr, "Error: the sandbox doesn't use a new network namespace\n");
		exit(1);
	}

	pid_t child;
	if (find_child(pid, &child) == -1) {
		fprintf(stderr, "Error: cannot join the network namespace\n");
		exit(1);
	}

	EUID_ROOT();
	if (join_namespace(child, "net")) {
		fprintf(stderr, "Error: cannot join the network namespace\n");
		exit(1);
	}

	if (strcmp(command, "set") == 0)
		bandwidth_set(pid, dev, down, up);
	else if (strcmp(command, "clear") == 0)
		bandwidth_remove(pid, dev);

	char *devname = NULL;
	if (dev) {
		char *fname;
		if (asprintf(&fname, "%s/%d-netmap", RUN_FIREJAIL_NETWORK_DIR, (int) pid) == -1)
			errExit("asprintf");
		FILE *fp = fopen(fname, "r");
		if (!fp) {
			fprintf(stderr, "Error: cannot read network map file %s\n", fname);
			exit(1);
		}
		
		char buf[1024];
		int len = strlen(dev);
		while (fgets(buf, 1024, fp)) {
			char *ptr = strchr(buf, '\n');
			if (ptr)
				*ptr = '\0';
			if (*buf == '\0')
				break;

			if (strncmp(buf, dev, len) == 0  && buf[len] == ':') {
				devname = strdup(buf + len + 1);
				if (!devname)
					errExit("strdup");
				if (if_nametoindex(devname) == 0) {
					fprintf(stderr, "Error: cannot find network device %s\n", devname);
					exit(1);
				}
				break;
			}
		}
		free(fname);
		fclose(fp);
	}
	
	char *cmd = NULL;
	if (devname) {
		if (strcmp(command, "set") == 0) {
			if (asprintf(&cmd, "%s/firejail/fshaper.sh --%s %s %d %d",
				LIBDIR, command, devname, down, up) == -1)
				errExit("asprintf");
		}
		else {
			if (asprintf(&cmd, "%s/firejail/fshaper.sh --%s %s",
				LIBDIR, command, devname) == -1)
				errExit("asprintf");
		}
	}
	else {
		if (asprintf(&cmd, "%s/firejail/fshaper.sh --%s", LIBDIR, command) == -1)
			errExit("asprintf");
	}
	assert(cmd);

	environ = NULL;

	if (setreuid(0, 0))
		errExit("setreuid");
 	if (setregid(0, 0))
 		errExit("setregid");
 
 	char *arg[4];
	arg[0] = "/bin/sh";
 	arg[1] = "-c";
 	arg[2] = cmd;
 	arg[3] = NULL;
	clearenv();
	execvp(arg[0], arg);
	
	errExit("execvp");
}