Ejemplo n.º 1
0
char *fd_load(int fd, size_t *psize, size_t maxsize)
{
    SMB_STRUCT_STAT sbuf;
    size_t size;
    char *p;

    if (sys_fstat(fd, &sbuf) != 0) {
        return NULL;
    }

    size = sbuf.st_size;
    if (maxsize) {
        size = MIN(size, maxsize);
    }

    p = (char *)SMB_MALLOC(size+1);
    if (!p) {
        return NULL;
    }

    if (read(fd, p, size) != size) {
        SAFE_FREE(p);
        return NULL;
    }
    p[size] = 0;

    if (psize) {
        *psize = size;
    }

    return p;
}
Ejemplo n.º 2
0
char *fd_load(int fd, size_t *size)
{
	SMB_STRUCT_STAT sbuf;
	char *p;

	if (sys_fstat(fd, &sbuf) != 0) {
		return NULL;
	}

	p = (char *)SMB_MALLOC(sbuf.st_size+1);
	if (!p) {
		return NULL;
	}

	if (read(fd, p, sbuf.st_size) != sbuf.st_size) {
		SAFE_FREE(p);
		return NULL;
	}
	p[sbuf.st_size] = 0;

	if (size) {
		*size = sbuf.st_size;
	}

	return p;
}
Ejemplo n.º 3
0
void __attribute__((destructor)) __ibprof_exit(void)
{
	IBPROF_ERROR status = IBPROF_ERR_NONE;
	UNREFERENCED_PARAMETER(status);

	/* check if it has been activated */
	if (ibprof_obj) {
		IBPROF_MODULE_OBJECT *temp_module_obj = NULL;
		int i = 0;

		ibprof_obj->task_obj->wall_time =
			ibprof_task_wall_time(ibprof_obj->task_obj->t_start);

		/* Dump all gathered information */
		ibprof_dump();

		temp_module_obj = ibprof_obj->module_array[0];
		while (temp_module_obj) {
			if (temp_module_obj->id != IBPROF_MODULE_INVALID) {
				if (temp_module_obj->exit)
					status = temp_module_obj->exit(temp_module_obj);
			}
			temp_module_obj = ibprof_obj->module_array[++i];
		}

		ibprof_hash_destroy(ibprof_obj->hash_obj);

		ibprof_task_destroy(ibprof_obj->task_obj);

		DELETE_CRITICAL(&(ibprof_obj->lock));

		sys_free(ibprof_obj);
		ibprof_obj = NULL;
	}

	if (ibprof_dump_file &&
		ibprof_dump_file != stdout &&
		ibprof_dump_file != stderr) {

		struct stat     statbuf;
		char fd_path[255];
		char *filename = sys_malloc(255);
		size_t ret = 0;

		sys_sprintf(fd_path, "/proc/self/fd/%d", fileno(ibprof_dump_file));

		ret = readlink(fd_path, filename, 255);

		if (ret > 0) {
			sys_fflush(ibprof_dump_file);
			sys_fclose(ibprof_dump_file);
			if (!sys_fstat(filename, &statbuf))
				if (!statbuf.st_size)
					  ret = sys_fremove(filename);
		}
	        sys_free(filename);
	}

	return ;
}
Ejemplo n.º 4
0
Archivo: debug.c Proyecto: jophxy/samba
void check_log_size( void )
{
	int         maxlog;
	SMB_STRUCT_STAT st;

	/*
	 *  We need to be root to check/change log-file, skip this and let the main
	 *  loop check do a new check as root.
	 */

	if( geteuid() != 0 )
		return;

	if(log_overflow || !need_to_check_log_size() )
		return;

	maxlog = lp_max_log_size() * 1024;

	if( sys_fstat( fileno( dbf ), &st ) == 0 && st.st_size > maxlog ) {
		(void)reopen_logs();
		if( dbf && get_file_size( debugf ) > maxlog ) {
			pstring name;

			slprintf( name, sizeof(name)-1, "%s.old", debugf );
			(void)rename( debugf, name );
      
			if (!reopen_logs()) {
				/* We failed to reopen a log - continue using the old name. */
				(void)rename(name, debugf);
			}
		}
	}

	/*
	 * Here's where we need to panic if dbf == NULL..
	 */

	if(dbf == NULL) {
		/* This code should only be reached in very strange
			circumstances. If we merely fail to open the new log we
			should stick with the old one. ergo this should only be
			reached when opening the logs for the first time: at
			startup or when the log level is increased from zero.
			-dwg 6 June 2000
		*/
		dbf = sys_fopen( "/dev/console", "w" );
		if(dbf) {
			DEBUG(0,("check_log_size: open of debug file %s failed - using console.\n",
					debugf ));
		} else {
			/*
			 * We cannot continue without a debug file handle.
			 */
			abort();
		}
	}
	debug_count = 0;
} /* check_log_size */
Ejemplo n.º 5
0
int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf)
{
	int result;

	START_PROFILE(syscall_fstat);
	result = sys_fstat(fd, sbuf);
	END_PROFILE(syscall_fstat);
	return result;
}
Ejemplo n.º 6
0
static void check_magic(files_struct *fsp,connection_struct *conn)
{
	if (!*lp_magicscript(SNUM(conn)))
		return;

	DEBUG(5,("checking magic for %s\n",fsp->fsp_name));

	{
		char *p;
		if (!(p = strrchr_m(fsp->fsp_name,'/')))
			p = fsp->fsp_name;
		else
			p++;

		if (!strequal(lp_magicscript(SNUM(conn)),p))
			return;
	}

	{
		int ret;
		pstring magic_output;
		pstring fname;
		SMB_STRUCT_STAT st;
		int tmp_fd, outfd;

		pstrcpy(fname,fsp->fsp_name);
		if (*lp_magicoutput(SNUM(conn)))
			pstrcpy(magic_output,lp_magicoutput(SNUM(conn)));
		else
			slprintf(magic_output,sizeof(fname)-1, "%s.out",fname);

		chmod(fname,0755);
		ret = smbrun(fname,&tmp_fd);
		DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
		unlink(fname);
		if (ret != 0 || tmp_fd == -1) {
			if (tmp_fd != -1)
				close(tmp_fd);
			return;
		}
		outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
		if (outfd == -1) {
			close(tmp_fd);
			return;
		}

		if (sys_fstat(tmp_fd,&st) == -1) {
			close(tmp_fd);
			close(outfd);
			return;
		}

		transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_size);
		close(tmp_fd);
		close(outfd);
	}
}
Ejemplo n.º 7
0
int sys_lstat(const char* pathname, struct stat* st) {
    int fd = sys_open(pathname, O_RDONLY | O_NOFOLLOW, 0);
    if(fd < 0)
        return -1;

    register int r = sys_fstat(fd, st);
    sys_close(fd);

    return r; 
});
Ejemplo n.º 8
0
/*
 * stat a file by file descriptor
 */
int fstat(int fd, struct stat * st)
{
	struct file_t * fp;

	if(fd < 0)
		return -1;

	if((fp = get_fp(fd)) == NULL)
		return -1;

	return sys_fstat(fp, st);
}
Ejemplo n.º 9
0
void check_log_size( void )
{
  int         maxlog;
  SMB_STRUCT_STAT st;

  /*
   *  We need to be root to check/change log-file, skip this and let the main
   *  loop check do a new check as root.
   */

  if( geteuid() != 0 )
    return;

  if( !need_to_check_log_size() )
    return;

  maxlog = lp_max_log_size() * 1024;

  if( sys_fstat( fileno( dbf ), &st ) == 0 && st.st_size > maxlog )
    {
    (void)fclose( dbf );
    dbf = NULL;
    reopen_logs();
    if( dbf && get_file_size( debugf ) > maxlog )
      {
      pstring name;

      (void)fclose( dbf );
      dbf = NULL;
      slprintf( name, sizeof(name)-1, "%s.old", debugf );
      (void)rename( debugf, name );
      reopen_logs();
      }
    }
  /*
   * Here's where we need to panic if dbf == NULL..
   */
  if(dbf == NULL) {
    dbf = sys_fopen( "/dev/console", "w" );
    if(dbf) {
      DEBUG(0,("check_log_size: open of debug file %s failed - using console.\n",
            debugf ));
    } else {
      /*
       * We cannot continue without a debug file handle.
       */
      abort();
    }
  }
  debug_count = 0;
} /* check_log_size */
Ejemplo n.º 10
0
int print_spool_write(files_struct *fsp,
		      const char *data, uint32_t size,
		      SMB_OFF_T offset, uint32_t *written)
{
	SMB_STRUCT_STAT st;
	ssize_t n;
	int ret;

	*written = 0;

	/* first of all stat file to find out if it is still there.
	 * spoolss may have deleted it to signal someone has killed
	 * the job through it's interface */

	if (sys_fstat(fsp->fh->fd, &st, false) != 0) {
		ret = errno;
		DEBUG(3, ("printfile_offset: sys_fstat failed on %s (%s)\n",
			  fsp_str_dbg(fsp), strerror(ret)));
		return ret;
	}

	/* check if the file is unlinked, this will signal spoolss has
	 * killed it, just return an error and close the file */
	if (st.st_ex_nlink == 0) {
		close(fsp->fh->fd);
		return EBADF;
	}

	/* When print files go beyond 4GB, the 32-bit offset sent in
	 * old SMBwrite calls is relative to the current 4GB chunk
	 * we're writing to.
	 *    Discovered by Sebastian Kloska <*****@*****.**>.
	 */
	if (offset < 0xffffffff00000000LL) {
		offset = (st.st_ex_size & 0xffffffff00000000LL) + offset;
	}

	n = write_data_at_offset(fsp->fh->fd, data, size, offset);
	if (n == -1) {
		ret = errno;
		print_spool_terminate(fsp->conn, fsp->print_file);
	} else {
		*written = n;
		ret = 0;
	}

	return ret;
}
Ejemplo n.º 11
0
static void dotareof(int f)
{
	SMB_STRUCT_STAT stbuf;
	/* Two zero blocks at end of file, write out full buffer */

	if (dry_run)
		return;

	(void) dozerobuf(f, TBLOCK);
	(void) dozerobuf(f, TBLOCK);

	if (sys_fstat(f, &stbuf) == -1) {
		DEBUG(0, ("Couldn't stat file handle\n"));
		return;
	}

	/* Could be a pipe, in which case S_ISREG should fail,
		* and we should write out at full size */
	if (tp > 0)
		write(f, tarbuf, S_ISREG(stbuf.st_mode) ? tp : tbufsiz);
}
Ejemplo n.º 12
0
uint32_t elf_load_fd(struct sys_state *sys, int fd, int flags, struct elf_load_info *info)
{
	uint32_t entry;
	stat_s stat;
	void *base;
	int err;

	err = sys_fstat(fd, &stat);
	if (err) {
		debug("Failed to stat ELF (%d)\n", err);
		sys_exit(1);
	}

	base = sys_mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
	if (IS_ERROR(base)) {
		debug("Failed to mmap ELF file\n");
		sys_exit(1);
	}

	entry = elf_load(sys, base, flags, info);
	sys_munmap(base, stat.st_size);
	return entry;
}
Ejemplo n.º 13
0
static NTSTATUS check_magic(struct files_struct *fsp)
{
	int ret;
	const char *magic_output = NULL;
	SMB_STRUCT_STAT st;
	int tmp_fd, outfd;
	TALLOC_CTX *ctx = NULL;
	const char *p;
	struct connection_struct *conn = fsp->conn;
	char *fname = NULL;
	NTSTATUS status;

	if (!*lp_magic_script(talloc_tos(), SNUM(conn))) {
		return NT_STATUS_OK;
	}

	DEBUG(5,("checking magic for %s\n", fsp_str_dbg(fsp)));

	ctx = talloc_stackframe();

	fname = fsp->fsp_name->base_name;

	if (!(p = strrchr_m(fname,'/'))) {
		p = fname;
	} else {
		p++;
	}

	if (!strequal(lp_magic_script(talloc_tos(), SNUM(conn)),p)) {
		status = NT_STATUS_OK;
		goto out;
	}

	if (*lp_magic_output(talloc_tos(), SNUM(conn))) {
		magic_output = lp_magic_output(talloc_tos(), SNUM(conn));
	} else {
		magic_output = talloc_asprintf(ctx,
				"%s.out",
				fname);
	}
	if (!magic_output) {
		status = NT_STATUS_NO_MEMORY;
		goto out;
	}

	/* Ensure we don't depend on user's PATH. */
	p = talloc_asprintf(ctx, "./%s", fname);
	if (!p) {
		status = NT_STATUS_NO_MEMORY;
		goto out;
	}

	if (chmod(fname, 0755) == -1) {
		status = map_nt_error_from_unix(errno);
		goto out;
	}
	ret = smbrun(p,&tmp_fd);
	DEBUG(3,("Invoking magic command %s gave %d\n",
		p,ret));

	unlink(fname);
	if (ret != 0 || tmp_fd == -1) {
		if (tmp_fd != -1) {
			close(tmp_fd);
		}
		status = NT_STATUS_UNSUCCESSFUL;
		goto out;
	}
	outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
	if (outfd == -1) {
		int err = errno;
		close(tmp_fd);
		status = map_nt_error_from_unix(err);
		goto out;
	}

	if (sys_fstat(tmp_fd, &st, false) == -1) {
		int err = errno;
		close(tmp_fd);
		close(outfd);
		status = map_nt_error_from_unix(err);
		goto out;
	}

	if (transfer_file(tmp_fd,outfd,(off_t)st.st_ex_size) == (off_t)-1) {
		int err = errno;
		close(tmp_fd);
		close(outfd);
		status = map_nt_error_from_unix(err);
		goto out;
	}
	close(tmp_fd);
	if (close(outfd) == -1) {
		status = map_nt_error_from_unix(errno);
		goto out;
	}

	status = NT_STATUS_OK;

 out:
	TALLOC_FREE(ctx);
	return status;
}
Ejemplo n.º 14
0
int
fstat(int fd, struct stat *stat) {
    return sys_fstat(fd, stat);
}
Ejemplo n.º 15
0
// unbounded_channels <= 0 means no, > 0 means yes
// -1 means advance.
void check_channel(char threadsafe, qio_chtype_t type, int64_t start, int64_t len, int64_t chunksz, qio_hint_t file_hints, qio_hint_t ch_hints, char unbounded_channels, char reopen)
{
  qio_file_t* f;
  qio_channel_t* writing;
  qio_channel_t* reading;
  int64_t offset;
  int64_t usesz;
  int64_t end = start + len;
  int err;
  unsigned char* chunk;
  unsigned char* got_chunk;
  int64_t k;
  ssize_t amt_written;
  ssize_t amt_read;
  char* chhints;
  char* fhints;
  FILE* writefp = NULL;
  FILE* readfp = NULL;
  int memory;
  int64_t ch_end = end;
  char filename[128];
  int fd = -1;

  strcpy(filename,"/tmp/qio_testXXXXXX");

  if( unbounded_channels > 0 ) ch_end = INT64_MAX;

  ch_hints = (ch_hints & ~ QIO_CHTYPEMASK) | type;

  memory = 0;

  if( (file_hints & QIO_METHODMASK) == QIO_METHOD_MEMORY ||
      (ch_hints & QIO_METHODMASK) == QIO_METHOD_MEMORY ) {
    memory = 1;
  }
  if( memory ) {
    file_hints = (file_hints & ~ QIO_METHODMASK ) | QIO_METHOD_MEMORY;
    ch_hints = (ch_hints & ~ QIO_METHODMASK ) | QIO_METHOD_MEMORY;
  }
  if( memory && type == QIO_CH_ALWAYS_UNBUFFERED ) return;
  if( memory && reopen ) return;
  if( (ch_hints & QIO_METHODMASK) == QIO_METHOD_FREADFWRITE ) {
    if( (file_hints & QIO_METHODMASK) != QIO_METHOD_FREADFWRITE ) return;
  }
  if( (ch_hints & QIO_METHODMASK) == QIO_METHOD_MMAP ) {
    if( (file_hints & QIO_METHODMASK) != QIO_METHOD_MMAP ) return;
  }

  fhints = qio_hints_to_string(file_hints);
  chhints = qio_hints_to_string(ch_hints);
  printf("check_channel(threadsafe=%i, type=%i, start=%lli, len=%lli, chunksz=%lli, file_hints=%s, ch_hints=%s, unbounded=%i, reopen=%i)\n",
         (int) threadsafe,
         (int) type,
         (long long int) start,
         (long long int) len,
         (long long int) chunksz,
         fhints,
         chhints,
         (int) unbounded_channels,
         (int) reopen );
  free(fhints);
  free(chhints);

  chunk = malloc(chunksz);
  got_chunk = malloc(chunksz);

  assert(chunk);
  assert(got_chunk);

  if( memory ) {
    err = qio_file_open_mem_ext(&f, NULL, QIO_FDFLAG_READABLE|QIO_FDFLAG_WRITEABLE|QIO_FDFLAG_SEEKABLE, file_hints, NULL);
    assert(!err);
  } else {
    // Open a temporary file.
    if( reopen ) {
      fd = mkstemp(filename);
      close(fd);
      err = qio_file_open_access(&f, filename, "w", file_hints, NULL);
      assert(!err);
    } else {
      err = qio_file_open_tmp(&f, file_hints, NULL);
      assert(!err);
    }

    // Rewind the file
    if (f->fp ) {
      int got;
      got = fseek(f->fp, start, SEEK_SET);
      assert( got == 0 );
    } else {
      off_t off;

      err = sys_lseek(f->fd, start, SEEK_SET, &off);
      assert(!err);
    }
  }

  // Create a "write to file" channel.
  err = qio_channel_create(&writing, f, ch_hints, 0, 1, start, ch_end, NULL);
  assert(!err);

  // Write stuff to the file.
  for( offset = start; offset < end; offset += usesz ) {
    usesz = chunksz;
    if( offset + usesz > end ) usesz = end - offset;
    // Fill chunk.
    fill_testdata(offset, usesz, chunk);
    // Write chunk.
    if( writefp ) {
      amt_written = fwrite(chunk, 1, usesz, writefp);
    } else {
      err = qio_channel_write(threadsafe, writing, chunk, usesz, &amt_written);
      assert(!err);
    }
    assert(amt_written == usesz);

  }

  // Attempt to write 1 more byte; we should get EEOF
  // if we've restricted the range of the channel.
  // Write chunk.
  if( unbounded_channels > 0) {
    // do nothing
  } else {
    if( writefp ) {
      int got;
      got = fflush(writefp);
      assert(got == 0);
      amt_written = fwrite(chunk, 1, 1, writefp);
      // fwrite might buffer on its own.
      if( amt_written != 0 ) {
        got = fflush(writefp);
        assert(got == EOF);
      }
      assert(errno == EEOF);
    } else {
      if( unbounded_channels < 0 ) {
        int times = -unbounded_channels;
        for( int z = 0; z < times; z++ ) {
          err = qio_channel_advance(threadsafe, writing, 1);
          assert( !err );
        }
      }

      err = qio_channel_write(threadsafe, writing, chunk, 1, &amt_written);
      assert(amt_written == 0);
      assert( err == EEOF );
    }
  }

  qio_channel_release(writing);

  // Reopen the file if we're doing reopen
  if( reopen ) {
    // Close the file.
    qio_file_release(f);
    err = qio_file_open_access(&f, filename, "r", file_hints, NULL);
    assert(!err);
  }

  // Check that the file is the right length.
  if( !memory ) {
    struct stat stats;
    err = sys_fstat(f->fd, &stats);
    assert(!err);
    assert(stats.st_size == end);
  }

  // That was fun. Now start at the beginning of the file
  // and read the data.
  
  // Rewind the file 
  if( !memory ) {
    off_t off;

    sys_lseek(f->fd, start, SEEK_SET, &off);
    assert(!err);
  }

  // Read the data.
  //err = qio_channel_init_file(&reading, type, f, ch_hints, 1, 0, start, end);
  err = qio_channel_create(&reading, f, ch_hints, 1, 0, start, ch_end, NULL);
  assert(!err);

  // Read stuff from the file.
  for( offset = start; offset < end; offset += usesz ) {
    usesz = chunksz;
    if( offset + usesz > end ) usesz = end - offset;
    // Fill chunk.
    fill_testdata(offset, usesz, chunk);
    memset(got_chunk, 0xff, usesz);
    // Read chunk.
    if( readfp ) {
      amt_read = fread(got_chunk, 1, usesz, readfp);
    } else {
      err = qio_channel_read(threadsafe, reading, got_chunk, usesz, &amt_read);
      assert( err == EEOF || err == 0);
    }
    assert(amt_read == usesz);

    // Compare chunk.
    for( k = 0; k < usesz; k++ ) {
      assert(got_chunk[k] == chunk[k]);
    }
  }

  if( readfp ) {
    amt_read = fread(got_chunk, 1, 1, readfp);
    assert( amt_read == 0 );
    assert( feof(readfp) );
  } else {
    if( unbounded_channels < 0 ) {
      int times = -unbounded_channels;
      for( int z = 0; z < times; z++ ) {
        err = qio_channel_advance(threadsafe, reading, 1);
        assert( !err );
      }

      err = qio_channel_advance(threadsafe, reading, -unbounded_channels);
      assert( !err );
    }

    err = qio_channel_read(threadsafe, reading, got_chunk, 1, &amt_read);
    assert( err == EEOF );
  }

  qio_channel_release(reading);
  //err = qio_channel_destroy(&reading);

  // Close the file.
  qio_file_release(f);

  if( reopen ) {
    unlink(filename);
  }

  free(chunk);
  free(got_chunk);
}
Ejemplo n.º 16
0
NTSTATUS print_spool_open(files_struct *fsp,
			  const char *fname,
			  uint16_t current_vuid)
{
	NTSTATUS status;
	TALLOC_CTX *tmp_ctx;
	struct print_file_data *pf;
	struct dcerpc_binding_handle *b = NULL;
	struct spoolss_DevmodeContainer devmode_ctr;
	union spoolss_DocumentInfo info;
	int fd = -1;
	WERROR werr;

	tmp_ctx = talloc_new(fsp);
	if (!tmp_ctx) {
		return NT_STATUS_NO_MEMORY;
	}

	pf = talloc_zero(fsp, struct print_file_data);
	if (!pf) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}
	pf->svcname = talloc_strdup(pf, lp_servicename(SNUM(fsp->conn)));

	/* the document name is derived from the file name.
	 * "Remote Downlevel Document" is added in front to
	 * mimic what windows does in this case */
	pf->docname = talloc_strdup(pf, DOCNAME_DEFAULT);
	if (!pf->docname) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}
	if (fname) {
		const char *p = strrchr(fname, '/');
		if (!p) {
			p = fname;
		}
		pf->docname = talloc_asprintf_append(pf->docname, " %s", p);
		if (!pf->docname) {
			status = NT_STATUS_NO_MEMORY;
			goto done;
		}
	}

	/*
	 * Ok, now we have to open an actual file.
	 * Here is the reason:
	 * We want to write the spool job to this file in
	 * smbd for scalability reason (and also because
	 * apparently window printer drivers can seek when
	 * spooling to a file).
	 * So we first create a file, and then we pass it
	 * to spoolss in output_file so it can monitor and
	 * take over once we call EndDocPrinter().
	 * Of course we will not start writing until
	 * StartDocPrinter() actually gives the ok.
	 * smbd spooler files do not include a print jobid
	 * path component, as the jobid is only known after
	 * calling StartDocPrinter().
	 */

	pf->filename = talloc_asprintf(pf, "%s/%sXXXXXX",
					lp_pathname(SNUM(fsp->conn)),
					PRINT_SPOOL_PREFIX);
	if (!pf->filename) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}
	errno = 0;
	fd = mkstemp(pf->filename);
	if (fd == -1) {
		if (errno == EACCES) {
			/* Common setup error, force a report. */
			DEBUG(0, ("Insufficient permissions "
				  "to open spool file %s.\n",
				  pf->filename));
		} else {
			/* Normal case, report at level 3 and above. */
			DEBUG(3, ("can't open spool file %s,\n",
				  pf->filename));
			DEBUGADD(3, ("errno = %d (%s).\n",
				     errno, strerror(errno)));
		}
		status = map_nt_error_from_unix(errno);
		goto done;
	}

	/* now open a document over spoolss so that it does
	 * all printer verification, and eventually assigns
	 * a job id */

	status = rpc_pipe_open_interface(fsp->conn,
					 &ndr_table_spoolss.syntax_id,
					 fsp->conn->session_info,
					 &fsp->conn->sconn->client_id,
					 fsp->conn->sconn->msg_ctx,
					 &fsp->conn->spoolss_pipe);
	if (!NT_STATUS_IS_OK(status)) {
		goto done;
	}
	b = fsp->conn->spoolss_pipe->binding_handle;

	ZERO_STRUCT(devmode_ctr);

	status = dcerpc_spoolss_OpenPrinter(b, pf, pf->svcname,
					    "RAW", devmode_ctr,
					    SEC_FLAG_MAXIMUM_ALLOWED,
					    &pf->handle, &werr);
	if (!NT_STATUS_IS_OK(status)) {
		goto done;
	}
	if (!W_ERROR_IS_OK(werr)) {
		status = werror_to_ntstatus(werr);
		goto done;
	}

	info.info1 = talloc(tmp_ctx, struct spoolss_DocumentInfo1);
	if (!info.info1) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}
	info.info1->document_name = pf->docname;
	info.info1->output_file = pf->filename;
	info.info1->datatype = "RAW";

	status = dcerpc_spoolss_StartDocPrinter(b, tmp_ctx, &pf->handle,
						1, info, &pf->jobid, &werr);
	if (!NT_STATUS_IS_OK(status)) {
		goto done;
	}
	if (!W_ERROR_IS_OK(werr)) {
		status = werror_to_ntstatus(werr);
		goto done;
	}

	/* Convert to RAP id. */
	pf->rap_jobid = pjobid_to_rap(pf->svcname, pf->jobid);
	if (pf->rap_jobid == 0) {
		/* No errno around here */
		status = NT_STATUS_ACCESS_DENIED;
		goto done;
	}

	/* setup a full fsp */
	status = create_synthetic_smb_fname(fsp, pf->filename, NULL,
					    NULL, &fsp->fsp_name);
	if (!NT_STATUS_IS_OK(status)) {
		goto done;
	}

	if (sys_fstat(fd, &fsp->fsp_name->st, false) != 0) {
		status = map_nt_error_from_unix(errno);
		goto done;
	}

	fsp->file_id = vfs_file_id_from_sbuf(fsp->conn, &fsp->fsp_name->st);
	fsp->mode = fsp->fsp_name->st.st_ex_mode;
	fsp->fh->fd = fd;

	fsp->vuid = current_vuid;
	fsp->can_lock = false;
	fsp->can_read = false;
	fsp->access_mask = FILE_GENERIC_WRITE;
	fsp->can_write = true;
	fsp->modified = false;
	fsp->oplock_type = NO_OPLOCK;
	fsp->sent_oplock_break = NO_BREAK_SENT;
	fsp->is_directory = false;

	fsp->print_file = pf;

	status = NT_STATUS_OK;
done:
	if (!NT_STATUS_IS_OK(status)) {
		if (fd != -1) {
			close(fd);
			if (fsp->print_file) {
				unlink(fsp->print_file->filename);
			}
		}
		/* We need to delete the job from spoolss too */
		if (pf->jobid) {
			print_spool_terminate(fsp->conn, pf);
		}
	}
	talloc_free(tmp_ctx);
	return status;
}
Ejemplo n.º 17
0
static void check_magic(struct files_struct *fsp)
{
    int ret;
    const char *magic_output = NULL;
    SMB_STRUCT_STAT st;
    int tmp_fd, outfd;
    TALLOC_CTX *ctx = NULL;
    const char *p;
    struct connection_struct *conn = fsp->conn;

    if (!*lp_magicscript(SNUM(conn))) {
        return;
    }

    DEBUG(5,("checking magic for %s\n",fsp->fsp_name));

    if (!(p = strrchr_m(fsp->fsp_name,'/'))) {
        p = fsp->fsp_name;
    } else {
        p++;
    }

    if (!strequal(lp_magicscript(SNUM(conn)),p)) {
        return;
    }

    ctx = talloc_stackframe();

    if (*lp_magicoutput(SNUM(conn))) {
        magic_output = lp_magicoutput(SNUM(conn));
    } else {
        magic_output = talloc_asprintf(ctx,
                                       "%s.out",
                                       fsp->fsp_name);
    }
    if (!magic_output) {
        TALLOC_FREE(ctx);
        return;
    }

    /* Ensure we don't depend on user's PATH. */
    p = talloc_asprintf(ctx, "./%s", fsp->fsp_name);
    if (!p) {
        TALLOC_FREE(ctx);
        return;
    }

    if (chmod(fsp->fsp_name,0755) == -1) {
        TALLOC_FREE(ctx);
        return;
    }
    ret = smbrun(p,&tmp_fd);
    DEBUG(3,("Invoking magic command %s gave %d\n",
             p,ret));

    unlink(fsp->fsp_name);
    if (ret != 0 || tmp_fd == -1) {
        if (tmp_fd != -1) {
            close(tmp_fd);
        }
        TALLOC_FREE(ctx);
        return;
    }
    outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
    if (outfd == -1) {
        close(tmp_fd);
        TALLOC_FREE(ctx);
        return;
    }

    if (sys_fstat(tmp_fd,&st) == -1) {
        close(tmp_fd);
        close(outfd);
        return;
    }

#ifdef AVM_VERY_SMALL
    AVM_VERY_SMALL_LOG
#else
    transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_size);
#endif

    close(tmp_fd);
    close(outfd);
    TALLOC_FREE(ctx);
}
Ejemplo n.º 18
0
static void ListerThread(struct ListerParams *args) {
  int                found_parent = 0;
  pid_t              clone_pid  = sys_gettid(), ppid = sys_getppid();
  char               proc_self_task[80], marker_name[48], *marker_path;
  const char         *proc_paths[3];
  const char *const  *proc_path = proc_paths;
  int                proc = -1, marker = -1, num_threads = 0;
  int                max_threads = 0, sig;
  struct kernel_stat marker_sb, proc_sb;
  stack_t            altstack;

  /* Create "marker" that we can use to detect threads sharing the same
   * address space and the same file handles. By setting the FD_CLOEXEC flag
   * we minimize the risk of misidentifying child processes as threads;
   * and since there is still a race condition,  we will filter those out
   * later, anyway.
   */
  if ((marker = sys_socket(PF_LOCAL, SOCK_DGRAM, 0)) < 0 ||
      sys_fcntl(marker, F_SETFD, FD_CLOEXEC) < 0) {
  failure:
    args->result = -1;
    args->err    = errno;
    if (marker >= 0)
      NO_INTR(sys_close(marker));
    sig_marker = marker = -1;
    if (proc >= 0)
      NO_INTR(sys_close(proc));
    sig_proc = proc = -1;
    sys__exit(1);
  }

  /* Compute search paths for finding thread directories in /proc            */
  local_itoa(strrchr(strcpy(proc_self_task, "/proc/"), '\000'), ppid);
  strcpy(marker_name, proc_self_task);
  marker_path = marker_name + strlen(marker_name);
  strcat(proc_self_task, "/task/");
  proc_paths[0] = proc_self_task; /* /proc/$$/task/                          */
  proc_paths[1] = "/proc/";       /* /proc/                                  */
  proc_paths[2] = NULL;

  /* Compute path for marker socket in /proc                                 */
  local_itoa(strcpy(marker_path, "/fd/") + 4, marker);
  if (sys_stat(marker_name, &marker_sb) < 0) {
    goto failure;
  }

  /* Catch signals on an alternate pre-allocated stack. This way, we can
   * safely execute the signal handler even if we ran out of memory.
   */
  memset(&altstack, 0, sizeof(altstack));
  altstack.ss_sp    = args->altstack_mem;
  altstack.ss_flags = 0;
  altstack.ss_size  = ALT_STACKSIZE;
  sys_sigaltstack(&altstack, (const stack_t *)NULL);

  /* Some kernels forget to wake up traced processes, when the
   * tracer dies.  So, intercept synchronous signals and make sure
   * that we wake up our tracees before dying. It is the caller's
   * responsibility to ensure that asynchronous signals do not
   * interfere with this function.
   */
  sig_marker = marker;
  sig_proc   = -1;
  for (sig = 0; sig < sizeof(sync_signals)/sizeof(*sync_signals); sig++) {
    struct kernel_sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_sigaction_ = SignalHandler;
    sys_sigfillset(&sa.sa_mask);
    sa.sa_flags      = SA_ONSTACK|SA_SIGINFO|SA_RESETHAND;
    sys_sigaction(sync_signals[sig], &sa, (struct kernel_sigaction *)NULL);
  }
  
  /* Read process directories in /proc/...                                   */
  for (;;) {
    /* Some kernels know about threads, and hide them in "/proc"
     * (although they are still there, if you know the process
     * id). Threads are moved into a separate "task" directory. We
     * check there first, and then fall back on the older naming
     * convention if necessary.
     */
    if ((sig_proc = proc = c_open(*proc_path, O_RDONLY|O_DIRECTORY, 0)) < 0) {
      if (*++proc_path != NULL)
        continue;
      goto failure;
    }
    if (sys_fstat(proc, &proc_sb) < 0)
      goto failure;
    
    /* Since we are suspending threads, we cannot call any libc
     * functions that might acquire locks. Most notably, we cannot
     * call malloc(). So, we have to allocate memory on the stack,
     * instead. Since we do not know how much memory we need, we
     * make a best guess. And if we guessed incorrectly we retry on
     * a second iteration (by jumping to "detach_threads").
     *
     * Unless the number of threads is increasing very rapidly, we
     * should never need to do so, though, as our guestimate is very
     * conservative.
     */
    if (max_threads < proc_sb.st_nlink + 100)
      max_threads = proc_sb.st_nlink + 100;
    
    /* scope */ {
      pid_t pids[max_threads];
      int   added_entries = 0;
      sig_num_threads     = num_threads;
      sig_pids            = pids;
      for (;;) {
        struct kernel_dirent *entry;
        char buf[4096];
        ssize_t nbytes = sys_getdents(proc, (struct kernel_dirent *)buf,
                                      sizeof(buf));
        if (nbytes < 0)
          goto failure;
        else if (nbytes == 0) {
          if (added_entries) {
            /* Need to keep iterating over "/proc" in multiple
             * passes until we no longer find any more threads. This
             * algorithm eventually completes, when all threads have
             * been suspended.
             */
            added_entries = 0;
            sys_lseek(proc, 0, SEEK_SET);
            continue;
          }
          break;
        }
        for (entry = (struct kernel_dirent *)buf;
             entry < (struct kernel_dirent *)&buf[nbytes];
             entry = (struct kernel_dirent *)((char *)entry+entry->d_reclen)) {
          if (entry->d_ino != 0) {
            const char *ptr = entry->d_name;
            pid_t pid;
            
            /* Some kernels hide threads by preceding the pid with a '.'     */
            if (*ptr == '.')
              ptr++;
            
            /* If the directory is not numeric, it cannot be a
             * process/thread
             */
            if (*ptr < '0' || *ptr > '9')
              continue;
            pid = local_atoi(ptr);

            /* Attach (and suspend) all threads                              */
            if (pid && pid != clone_pid) {
              struct kernel_stat tmp_sb;
              char fname[entry->d_reclen + 48];
              strcat(strcat(strcpy(fname, "/proc/"),
                            entry->d_name), marker_path);
              
              /* Check if the marker is identical to the one we created      */
              if (sys_stat(fname, &tmp_sb) >= 0 &&
                  marker_sb.st_ino == tmp_sb.st_ino) {
                long i, j;

                /* Found one of our threads, make sure it is no duplicate    */
                for (i = 0; i < num_threads; i++) {
                  /* Linear search is slow, but should not matter much for
                   * the typically small number of threads.
                   */
                  if (pids[i] == pid) {
                    /* Found a duplicate; most likely on second pass         */
                    goto next_entry;
                  }
                }
                
                /* Check whether data structure needs growing                */
                if (num_threads >= max_threads) {
                  /* Back to square one, this time with more memory          */
                  NO_INTR(sys_close(proc));
                  goto detach_threads;
                }

                /* Attaching to thread suspends it                           */
                pids[num_threads++] = pid;
                sig_num_threads     = num_threads;
                if (sys_ptrace(PTRACE_ATTACH, pid, (void *)0,
                               (void *)0) < 0) {
                  /* If operation failed, ignore thread. Maybe it
                   * just died?  There might also be a race
                   * condition with a concurrent core dumper or
                   * with a debugger. In that case, we will just
                   * make a best effort, rather than failing
                   * entirely.
                   */
                  num_threads--;
                  sig_num_threads = num_threads;
                  goto next_entry;
                }
                while (sys_waitpid(pid, (int *)0, __WALL) < 0) {
                  if (errno != EINTR) {
                    sys_ptrace_detach(pid);
                    num_threads--;
                    sig_num_threads = num_threads;
                    goto next_entry;
                  }
                }
                
                if (sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i++ != j ||
                    sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i   != j) {
                  /* Address spaces are distinct, even though both
                   * processes show the "marker". This is probably
                   * a forked child process rather than a thread.
                   */
                  sys_ptrace_detach(pid);
                  num_threads--;
                  sig_num_threads = num_threads;
                } else {
                  found_parent |= pid == ppid;
                  added_entries++;
                }
              }
            }
          }
        next_entry:;
        }
      }
      NO_INTR(sys_close(proc));
      sig_proc = proc = -1;

      /* If we failed to find any threads, try looking somewhere else in
       * /proc. Maybe, threads are reported differently on this system.
       */
      if (num_threads > 1 || !*++proc_path) {
        NO_INTR(sys_close(marker));
        sig_marker = marker = -1;

        /* If we never found the parent process, something is very wrong.
         * Most likely, we are running in debugger. Any attempt to operate
         * on the threads would be very incomplete. Let's just report an
         * error to the caller.
         */
        if (!found_parent) {
          ResumeAllProcessThreads(num_threads, pids);
          sys__exit(3);
        }

        /* Now we are ready to call the callback,
         * which takes care of resuming the threads for us.
         */
        args->result = args->callback(args->parameter, num_threads,
                                      pids, args->ap);
        args->err = errno;

        /* Callback should have resumed threads, but better safe than sorry  */
        if (ResumeAllProcessThreads(num_threads, pids)) {
          /* Callback forgot to resume at least one thread, report error     */
          args->err    = EINVAL;
          args->result = -1;
        }

        sys__exit(0);
      }
    detach_threads:
      /* Resume all threads prior to retrying the operation                  */
      ResumeAllProcessThreads(num_threads, pids);
      sig_pids = NULL;
      num_threads = 0;
      sig_num_threads = num_threads;
      max_threads += 100;
    }
  }
}
Ejemplo n.º 19
0
void
syscall(struct trapframe *tf)
{
	int callno;
	int32_t retval;
	int err;

	KASSERT(curthread != NULL);
	KASSERT(curthread->t_curspl == 0);
	KASSERT(curthread->t_iplhigh_count == 0);

	callno = tf->tf_v0;

	/*
	 * Initialize retval to 0. Many of the system calls don't
	 * really return a value, just 0 for success and -1 on
	 * error. Since retval is the value returned on success,
	 * initialize it to 0 by default; thus it's not necessary to
	 * deal with it except for calls that return other values, 
	 * like write.
	 */

	retval = 0;

	uint32_t v0, v1;
	off_t pos;
	int whence;
	//userptr_t *status;

	struct stat statbuf;


	switch (callno) {
	    case SYS_reboot:
		err = sys_reboot(tf->tf_a0);
		break;

	    case SYS___time:
		err = sys___time((userptr_t)tf->tf_a0,
				 (userptr_t)tf->tf_a1);	 /* the syscall ov*/
		break;

	    case SYS_open:
	    err = sys_open((const_userptr_t)tf->tf_a0, tf->tf_a1, (mode_t)tf ->tf_a2, &retval);
	    break;

	    case SYS_close:
	    err = sys_close((tf->tf_a0),&retval);
	    break;

	    case SYS_read:
	    	err = sys_read(tf->tf_a0, (userptr_t)tf->tf_a1, (size_t)tf -> tf_a2, &retval);
	    	//retval = (int32_t)bytes;
	    	break;

	    case SYS_write:
	   	    err = sys_write(tf->tf_a0, (userptr_t)tf->tf_a1, (size_t)tf -> tf_a2, &retval);
	   	    //retval = (int32_t)bytes;
	   	    break;

	    case SYS_lseek:
	    	pos = tf->tf_a2;
	    	pos = pos << 32;
	    	pos += tf -> tf_a3;
	    	err = copyin((const_userptr_t)tf->tf_sp+16,&whence,sizeof(int));
	    	if(err)
	    	{
	    		break;
	    	}
	    	err = sys_lseek(tf->tf_a0, pos, whence, &v0, &v1);
	    	if(err)
	    	{
	    		break;
	    	}
	    	retval = v0;
	    	tf->tf_v1 = v1;
	    	break;

	    case SYS__exit:

	    	sys__exit(tf->tf_a0);


//			We are only here because of one of 2 reasons. We tried to kill the initial thread
//			while there was/were (an) immediate child(ren) of it running.

//			*NOTE* I'm actually NOT sure if that's a valid reason to be here

//			Second reason? Something went horribly, horribly wrong
	    	err = 0;
	    	break;
 
	    case SYS_dup2:

	    	err = sys_dup2(tf->tf_a0,tf->tf_a1,&retval);
	    	break;

	    case SYS_fstat:

	    	err = sys_fstat(tf->tf_a0, &statbuf);
	    	break;

	    case SYS_fork:
	    	err = sys_fork(tf, &retval);
	    	break;

	    case SYS_getpid:
	    	err = sys_getpid(&retval);
	    	break;

	    case SYS_waitpid:
	    	err = sys_waitpid(tf->tf_a0, (int*)tf->tf_a1, (int)tf->tf_a2, &retval);
	    	break;

	    case SYS___getcwd:

	    	err = sys___getcwd((char*)tf->tf_a0,(size_t)tf->tf_a1,&retval);
	    	break;

	    case SYS_chdir:
	    	err = sys_chdir((char*)tf->tf_a0,&retval);
	    	break;

	    case SYS_execv:
	    	err = sys_execv((const char*)tf->tf_a0, (char**)tf->tf_a1);
	    	break;
	    case SYS_sbrk:
	    	err = sbrk((int)tf->tf_a0,&retval);
	    	break;

	    default:
		kprintf("Unknown syscall %d\n", callno);
		err = ENOSYS;
		break;
	}


	if (err) {
		/*
		 * Return the error code. This gets converted at
		 * userlevel to a return value of -1 and the error
		 * code in errno.
		 */
		tf->tf_v0 = err;
		tf->tf_a3 = 1;      /* signal an error */
	}
	else {
		/* Success. */
		tf->tf_v0 = retval;
		tf->tf_a3 = 0;      /* signal no error */
	}
	
	/*
	 * Now, advance the program counter, to avoid restarting
	 * the syscall over and over again.
	 */
	
	tf->tf_epc += 4;

	/* Make sure the syscall code didn't forget to lower spl */
	KASSERT(curthread->t_curspl == 0);
	/* ...or leak any spinlocks */
	KASSERT(curthread->t_iplhigh_count == 0);


}