Ошибка сегментации при выходе из системного вызова собственного ядра в c - PullRequest
0 голосов
/ 23 апреля 2020

В настоящее время я делаю системный вызов, который объединяет несколько файлов в один на уровне ядра.

Распечатав количество байтов, скопированных в сообщениях ядра, и проверив выходной файл, я вижу, что я может успешно объединить файлы в выходной файл.

Однако, когда мой системный вызов (xmerge. c) завершается и возвращается к моему пользовательскому пространственному коду (test_xmerge. c) для тестирования моего пользовательского системный вызов, происходит ошибка сегментации.

Ошибка, которую я получаю, когда "tail -50 / var / log / messages" выглядит следующим образом:

enter image description here

Кажется, что системный вызов не может вернуть количество общих байтов обратно в пространство пользователя (вернуть итог;), что вызывает ошибку сегментации в коде тестирования пространства пользователя.

Однако такой проблемы не возникает, когда система вызов возвращает код ошибки (return -EFAULT;), поскольку я могу распечатать возвращаемое значение в test_xmerge без ошибки сегментации.

Мой код для xmerge. c выглядит следующим образом:

//For xmerge.c placed in the linux-4.19.105/os-lab

#include <a bunch of includes>

struct xmerge_params{
  char __user *outfile; // name of the output file
  char __user **infiles;  // array with names of input files
  unsigned int num_files; // number of input files
  int oflags; // the open flag for the outfile
  mode_t mode;  // default permission mode for newly created outfile
  int __user *ofile_count;  // it will be updated as the number of files that have been read into outfile
};


SYSCALL_DEFINE2(xmerge, void*, args, size_t, argslen){

  struct xmerge_params ps;

  # Omit a bunch of variable init

  if (copy_from_user(&ps, args, argslen) != 0){
    printk(KERN_INFO "Cannot Copy From User\n");
    return -EFAULT; // This return -EFAULT would not cause segmentation fault
  }

  outfile = ksys_open(ps.outfile, ps.oflags, ps.mode);

  if (outfile < 0) {
    return outfile;  // This return outfile would not cause segmentation fault
  }

  for (i = 0; i < ps.num_files; i++){
    # Omit the file copying using buffer

    *(ps.ofile_count)++;
  }
  ksys_close(outfile);

  printk(KERN_INFO "Total: %d\n", total);
  set_fs(old_fs);

  if (copy_to_user(args, &ps, argslen) != 0){
    printk(KERN_INFO "Cannot Copy To User\n");
    return -EFAULT;
  }

  printk(KERN_INFO "Finish Syscall, total: %d\n", total);

  return total;  // Unable to return total
}

Для кода тестирования test_xmerge. c:

#include <a bunch of includes>

struct xmerge_params{
  char *outfile;  // name of the output file
  char **infiles; // array with names of input files
  unsigned int num_files; // number of input files
  int oflags; // the open flag for the outfile
  mode_t mode;  // default permission mode for newly created outfile
  int *ofile_count; // it will be updated as the number of files that have been read into outfile
};

int main(int argc, const char *argv[]){

  # Omit a bunch of variable init

  int flag;
  while ((flag = getopt(argc, argv, "actem:h")) != -1){
    switch (flag){
      # Omit dealing with the command line arguments
    }
  }

  # Omit setting up xmerge_params

  ps.ofile_count = (int*)malloc(100 * sizeof(int)); // Added this line fixed the segmentation problem
  *(ps.ofile_count) = 0;

  printf("Before call syscall\n");

  printf("*(ps.ofile_count)%d\n", *(ps.ofile_count)); // Value is 0

  res = syscall(SYSCALL_NUM_XMERGE, &ps, sizeof(struct xmerge_params));

  printf("*(ps.ofile_count)%d\n", *(ps.ofile_count)); // Value should be 2 but still output 0

  printf("After call syscall\n");

  if (res >= 0){
    printf("%d bytes from %d files are copied\n", res, *(ps.ofile_count));
  } else{
    printf("Error: %i %s\n", errno, strerror(errno));
  }

  return 0;
}

Может кто-нибудь помочь мне разобраться в проблеме? Так как я пытался выяснить проблему в течение нескольких дней, и отладка это раздражает, когда каждый раз, когда я хочу попробовать некоторые модификации, которые я должен сделать; делать модули; make modules_install; сделать установку. И подождите, пока он соберется и скомпилируется в течение 10 минут на моей виртуальной машине.

Обновление: после дальнейшей отладки я обнаружил, что проблема в том, что я не выделил память в test_xmerge. c для ps.ofile_count, и когда я увеличиваю ps.ofile_count в xmerge, я хочу увеличивать адрес, а не значение. Вот почему это вызвало ошибку сегментации.

Проблема сегментации была исправлена. Но возникла другая проблема: copy_to_user, похоже, не работает для ps.ofile_count. ie, когда я выводил ps.ofile count после итерации для l oop в xmerge, он выводится как 2 (так как у меня есть два файла для слияния). Однако, когда я вывожу его в test_xmerge после системного вызова, значение ps.ofile_count остается равным 0. Таким образом, кажется, что copy_to_user foes работает, поскольку значение ps.ofile_count не обновляется.

I удалили old_fs = get_fs () ;, set_fs (get_ds ()); и set_fs (old_fs); строка до и после copy_to_user. Но это не решает проблему.

Есть идеи, почему это происходит и как это исправить?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...