diff --git a/Informe.md b/Informe.md new file mode 100644 index 0000000000..6341442abd --- /dev/null +++ b/Informe.md @@ -0,0 +1,92 @@ +# Informe Oscar Lobo + +## Funcionamiento del Sistema de Permisos +El sistema de permisos básicos implementado en xv6 utiliza una nueva función de sistema chmod para gestionar permisos de archivos. Este sistema permite definir restricciones de acceso para los archivos en los siguientes modos: + +### Lectura/Escriptura: Permite operaciones tanto de lectura como escritura. +Solo Lectura: Restringe las operaciones de escritura en el archivo. +Inmutable: Marca el archivo como no modificable, tanto en contenido como en permisos. +Estas funcionalidades mejoran el control de acceso, garantizando la seguridad y consistencia de los archivos almacenados. + +### chmod +La función chmod permite cambiar los permisos asociados a un archivo. Sus características principales incluyen: + +Actualizar los permisos de un archivo especificado a los valores definidos por el usuario. +Proteger archivos inmutables (perm = 5) contra cualquier tipo de modificación, tanto en contenido como en permisos. + +## Modificaciones Realizadas + +### Archivo sysfile.c +Se realizaron las siguientes modificaciones para respetar los permisos: + +Función sys_open +Verifica los permisos del archivo antes de abrirlo: +Archivos de solo lectura (perm = 1) no pueden ser abiertos en modo escritura. +Archivos inmutables (perm = 5) solo pueden ser abiertos en modo lectura. +Función writei +Restringe las operaciones de escritura en archivos: +Si perm = 1 (solo lectura), la operación es denegada. +Si perm = 5 (inmutable), la operación también es denegada. +Archivo sysproc.c +Se implementó la función sys_chmod, que realiza las siguientes operaciones: + +Cambia los permisos del archivo especificado a los valores definidos por el usuario. +Devuelve un error si el archivo es inmutable (perm = 5). + +### Archivo syscall.h +Se añadió la definición de la nueva llamada al sistema + + +### Archivo usys.pl +Se agregó la entrada para la nueva función de sistema + +### Archivo chmodtest.c +Se creó un programa de prueba para validar las funcionalidades implementadas. Este programa realiza las siguientes operaciones: + +Creación del archivo: + +Crea un archivo con permisos iniciales de lectura/escritura (O_CREATE | O_RDWR). +Escribe datos en el archivo y lo cierra. +Cambio a solo lectura: + +Cambia los permisos del archivo a solo lectura (chmod(filename, 1)). +Intenta abrir el archivo en modo escritura, lo que debe fallar. +Restauración de permisos: + +Cambia los permisos a lectura/escritura (chmod(filename, 3)). +Escribe nuevamente en el archivo para confirmar los permisos. +Prueba de inmutabilidad: + +Cambia los permisos del archivo a inmutable (chmod(filename, 5)). +Intenta escribir en el archivo y modificar sus permisos, ambas operaciones deben fallar. +Manejo de Excepciones + +### Cambios en sysfile.c: +Se añadieron validaciones para los permisos definidos en inode al manejar operaciones de apertura, lectura y escritura. +Manejo en chmod: +Si un archivo es inmutable, la función devuelve un error, bloqueando cambios en sus permisos. +Pruebas + +## Descripción del Programa de Prueba +El programa chmodtest.c simula el uso de las nuevas funcionalidades de permisos en xv6. Sus pasos son: + +Crear un archivo con permisos de lectura/escritura. +Cambiar los permisos a solo lectura y verificar que la escritura sea denegada. +Restaurar los permisos y confirmar que la escritura sea posible. +Cambiar los permisos a inmutable y verificar que no se pueda ni escribir ni modificar sus permisos. +Resultados de las Pruebas +Archivos con permisos de solo lectura restringen correctamente la escritura. +Archivos inmutables bloquean modificaciones tanto en contenido como en permisos. +El sistema genera mensajes de error apropiados cuando se violan las restricciones. +Dificultades Encontradas y Soluciones +Desalineación de la estructura inode +La inclusión del campo perm en el inode aumentó su tamaño, rompiendo la alineación requerida con BSIZE. Esto generó errores durante la inicialización del sistema de archivos. La solución fue añadir un campo de relleno para garantizar que la estructura sea múltiplo de BSIZE. + +## Dificultades Encontradas y Soluciones + +### Manejo de errores +surgieron muchos errores al intentar hacer la tarea, los cuales tuve que apoyarme de otros compañeros para soluconarlos, ya que no encontraba solución en internet. + +### Validación de permisos +Inicialmente, las operaciones de escritura y apertura no verificaban correctamente los permisos. Este problema se resolvió añadiendo validaciones explícitas en las funciones sys_open y writei. + diff --git a/Makefile b/Makefile index f8c820ebd6..f7fc048e27 100644 --- a/Makefile +++ b/Makefile @@ -139,6 +139,7 @@ UPROGS=\ $U/_grind\ $U/_wc\ $U/_zombie\ + $U/_chmodtest\ fs.img: mkfs/mkfs README $(UPROGS) mkfs/mkfs fs.img README $(UPROGS) diff --git a/kernel/file.c b/kernel/file.c index 25fa2263ae..0fbda5a24a 100644 --- a/kernel/file.c +++ b/kernel/file.c @@ -178,5 +178,4 @@ filewrite(struct file *f, uint64 addr, int n) } return ret; -} - +} \ No newline at end of file diff --git a/kernel/file.h b/kernel/file.h index b076d1d806..d4ae54be65 100644 --- a/kernel/file.h +++ b/kernel/file.h @@ -27,6 +27,8 @@ struct inode { short nlink; uint size; uint addrs[NDIRECT+1]; + + int perm; // Nuevo campo para permisos o uso en memoria. }; // map major device number to device functions. @@ -37,4 +39,4 @@ struct devsw { extern struct devsw devsw[]; -#define CONSOLE 1 +#define CONSOLE 1 \ No newline at end of file diff --git a/kernel/fs.c b/kernel/fs.c index c6bab157e3..72bc1b757c 100644 --- a/kernel/fs.c +++ b/kernel/fs.c @@ -27,14 +27,14 @@ struct superblock sb; // Read the super block. -static void +void readsb(int dev, struct superblock *sb) { - struct buf *bp; + struct buf *bp; - bp = bread(dev, 1); - memmove(sb, bp->data, sizeof(*sb)); - brelse(bp); + bp = bread(dev, 1); + memmove(sb, bp->data, sizeof(*sb)); + brelse(bp); } // Init fs @@ -198,26 +198,28 @@ static struct inode* iget(uint dev, uint inum); struct inode* ialloc(uint dev, short type) { - int inum; - struct buf *bp; - struct dinode *dip; - - for(inum = 1; inum < sb.ninodes; inum++){ - bp = bread(dev, IBLOCK(inum, sb)); - dip = (struct dinode*)bp->data + inum%IPB; - if(dip->type == 0){ // a free inode - memset(dip, 0, sizeof(*dip)); - dip->type = type; - log_write(bp); // mark it allocated on the disk - brelse(bp); - return iget(dev, inum); + int inum; + struct buf *bp; + struct dinode *dip; + + for (inum = 1; inum < sb.ninodes; inum++) { + bp = bread(dev, IBLOCK(inum, sb)); + dip = (struct dinode*)bp->data + inum % IPB; + if (dip->type == 0) { // Un inodo libre + memset(dip, 0, sizeof(*dip)); + dip->type = type; + dip->perm = 0; // Inicializar permisos a 0 + log_write(bp); // Marcar como asignado en el disco + brelse(bp); + return iget(dev, inum); + } + brelse(bp); } - brelse(bp); - } - printf("ialloc: no inodes\n"); - return 0; + printf("ialloc: no inodes\n"); + return 0; } + // Copy a modified in-memory inode to disk. // Must be called after every change to an ip->xxx field // that lives on disk. @@ -225,21 +227,27 @@ ialloc(uint dev, short type) void iupdate(struct inode *ip) { - struct buf *bp; - struct dinode *dip; - - bp = bread(ip->dev, IBLOCK(ip->inum, sb)); - dip = (struct dinode*)bp->data + ip->inum%IPB; - dip->type = ip->type; - dip->major = ip->major; - dip->minor = ip->minor; - dip->nlink = ip->nlink; - dip->size = ip->size; - memmove(dip->addrs, ip->addrs, sizeof(ip->addrs)); - log_write(bp); - brelse(bp); + struct buf *bp; + struct dinode *dip; + + bp = bread(ip->dev, IBLOCK(ip->inum, sb)); + dip = (struct dinode *)bp->data + ip->inum % IPB; + + dip->type = ip->type; + dip->major = ip->major; + dip->minor = ip->minor; + dip->nlink = ip->nlink; + dip->size = ip->size; + + // Eliminar referencias a ip->perm porque ip es de tipo inode + // Si ip->perm no es relevante aquí, basta con sincronizar con dip->perm + memmove(dip->addrs, ip->addrs, sizeof(ip->addrs)); + log_write(bp); + brelse(bp); } + + // Find the inode with number inum on device dev // and return the in-memory copy. Does not lock // the inode and does not read it from disk. @@ -292,30 +300,35 @@ idup(struct inode *ip) void ilock(struct inode *ip) { - struct buf *bp; - struct dinode *dip; + struct buf *bp; + struct dinode *dip; - if(ip == 0 || ip->ref < 1) - panic("ilock"); + if (ip == 0 || ip->ref < 1) + panic("ilock"); - acquiresleep(&ip->lock); + acquiresleep(&ip->lock); - if(ip->valid == 0){ - bp = bread(ip->dev, IBLOCK(ip->inum, sb)); - dip = (struct dinode*)bp->data + ip->inum%IPB; - ip->type = dip->type; - ip->major = dip->major; - ip->minor = dip->minor; - ip->nlink = dip->nlink; - ip->size = dip->size; - memmove(ip->addrs, dip->addrs, sizeof(ip->addrs)); - brelse(bp); - ip->valid = 1; - if(ip->type == 0) - panic("ilock: no type"); - } + if (ip->valid == 0) { + bp = bread(ip->dev, IBLOCK(ip->inum, sb)); + dip = (struct dinode *)bp->data + ip->inum % IPB; + + ip->type = dip->type; + ip->major = dip->major; + ip->minor = dip->minor; + ip->nlink = dip->nlink; + ip->size = dip->size; + + // Eliminar cualquier referencia a ip->perm + memmove(ip->addrs, dip->addrs, sizeof(ip->addrs)); + brelse(bp); + ip->valid = 1; + if (ip->type == 0) + panic("ilock: no type"); + } } + + // Unlock the given inode. void iunlock(struct inode *ip) @@ -694,4 +707,4 @@ struct inode* nameiparent(char *path, char *name) { return namex(path, 1, name); -} +} \ No newline at end of file diff --git a/kernel/fs.h b/kernel/fs.h index 139dcc9c37..8029abd81c 100644 --- a/kernel/fs.h +++ b/kernel/fs.h @@ -30,12 +30,16 @@ struct superblock { // On-disk inode structure struct dinode { - short type; // File type - short major; // Major device number (T_DEVICE only) - short minor; // Minor device number (T_DEVICE only) - short nlink; // Number of links to inode in file system - uint size; // Size of file (bytes) - uint addrs[NDIRECT+1]; // Data block addresses + short type; // Tipo de archivo + short major; // Número de dispositivo mayor + short minor; // Número de dispositivo menor + short nlink; // Número de enlaces + uint size; // Tamaño del archivo en bytes + uint addrs[NDIRECT+1]; // Direcciones de bloques de datos + int perm; // Permisos del archivo + char padding[57]; // Ajusta el tamaño del padding según sea necesario + + //char padding[BSIZE - ((sizeof(short) * 3 + sizeof(uint) * (NDIRECT + 2) + sizeof(int)) % BSIZE)]; }; // Inodes per block. @@ -44,6 +48,8 @@ struct dinode { // Block containing inode i #define IBLOCK(i, sb) ((i) / IPB + sb.inodestart) +void readsb(int dev, struct superblock *sb); + // Bitmap bits per block #define BPB (BSIZE*8) @@ -56,5 +62,4 @@ struct dinode { struct dirent { ushort inum; char name[DIRSIZ]; -}; - +}; \ No newline at end of file diff --git a/kernel/riscv.h b/kernel/riscv.h index 8732ed970f..2026894423 100644 --- a/kernel/riscv.h +++ b/kernel/riscv.h @@ -1,11 +1,9 @@ #ifndef __ASSEMBLER__ // which hart (core) is this? -static inline uint64 -r_mhartid() -{ +static inline uint64 r_mhartid() { uint64 x; - asm volatile("csrr %0, mhartid" : "=r" (x) ); + asm volatile("csrr %0, mhartid" : "=r"(x)); return x; } @@ -17,27 +15,21 @@ r_mhartid() #define MSTATUS_MPP_U (0L << 11) #define MSTATUS_MIE (1L << 3) // machine-mode interrupt enable. -static inline uint64 -r_mstatus() -{ +static inline uint64 r_mstatus() { uint64 x; - asm volatile("csrr %0, mstatus" : "=r" (x) ); + asm volatile("csrr %0, mstatus" : "=r"(x)); return x; } -static inline void -w_mstatus(uint64 x) -{ - asm volatile("csrw mstatus, %0" : : "r" (x)); +static inline void w_mstatus(uint64 x) { + asm volatile("csrw mstatus, %0" : : "r"(x)); } // machine exception program counter, holds the // instruction address to which a return from // exception will go. -static inline void -w_mepc(uint64 x) -{ - asm volatile("csrw mepc, %0" : : "r" (x)); +static inline void w_mepc(uint64 x) { + asm volatile("csrw mepc, %0" : : "r"(x)); } // Supervisor Status Register, sstatus @@ -48,173 +40,131 @@ w_mepc(uint64 x) #define SSTATUS_SIE (1L << 1) // Supervisor Interrupt Enable #define SSTATUS_UIE (1L << 0) // User Interrupt Enable -static inline uint64 -r_sstatus() -{ +static inline uint64 r_sstatus() { uint64 x; - asm volatile("csrr %0, sstatus" : "=r" (x) ); + asm volatile("csrr %0, sstatus" : "=r"(x)); return x; } -static inline void -w_sstatus(uint64 x) -{ - asm volatile("csrw sstatus, %0" : : "r" (x)); +static inline void w_sstatus(uint64 x) { + asm volatile("csrw sstatus, %0" : : "r"(x)); } // Supervisor Interrupt Pending -static inline uint64 -r_sip() -{ +static inline uint64 r_sip() { uint64 x; - asm volatile("csrr %0, sip" : "=r" (x) ); + asm volatile("csrr %0, sip" : "=r"(x)); return x; } -static inline void -w_sip(uint64 x) -{ - asm volatile("csrw sip, %0" : : "r" (x)); +static inline void w_sip(uint64 x) { + asm volatile("csrw sip, %0" : : "r"(x)); } // Supervisor Interrupt Enable #define SIE_SEIE (1L << 9) // external #define SIE_STIE (1L << 5) // timer #define SIE_SSIE (1L << 1) // software -static inline uint64 -r_sie() -{ + +static inline uint64 r_sie() { uint64 x; - asm volatile("csrr %0, sie" : "=r" (x) ); + asm volatile("csrr %0, sie" : "=r"(x)); return x; } -static inline void -w_sie(uint64 x) -{ - asm volatile("csrw sie, %0" : : "r" (x)); +static inline void w_sie(uint64 x) { + asm volatile("csrw sie, %0" : : "r"(x)); } // Machine-mode Interrupt Enable #define MIE_STIE (1L << 5) // supervisor timer -static inline uint64 -r_mie() -{ + +static inline uint64 r_mie() { uint64 x; - asm volatile("csrr %0, mie" : "=r" (x) ); + asm volatile("csrr %0, mie" : "=r"(x)); return x; } -static inline void -w_mie(uint64 x) -{ - asm volatile("csrw mie, %0" : : "r" (x)); +static inline void w_mie(uint64 x) { + asm volatile("csrw mie, %0" : : "r"(x)); } // supervisor exception program counter, holds the // instruction address to which a return from // exception will go. -static inline void -w_sepc(uint64 x) -{ - asm volatile("csrw sepc, %0" : : "r" (x)); +static inline void w_sepc(uint64 x) { + asm volatile("csrw sepc, %0" : : "r"(x)); } -static inline uint64 -r_sepc() -{ +static inline uint64 r_sepc() { uint64 x; - asm volatile("csrr %0, sepc" : "=r" (x) ); + asm volatile("csrr %0, sepc" : "=r"(x)); return x; } // Machine Exception Delegation -static inline uint64 -r_medeleg() -{ +static inline uint64 r_medeleg() { uint64 x; - asm volatile("csrr %0, medeleg" : "=r" (x) ); + asm volatile("csrr %0, medeleg" : "=r"(x)); return x; } -static inline void -w_medeleg(uint64 x) -{ - asm volatile("csrw medeleg, %0" : : "r" (x)); +static inline void w_medeleg(uint64 x) { + asm volatile("csrw medeleg, %0" : : "r"(x)); } // Machine Interrupt Delegation -static inline uint64 -r_mideleg() -{ +static inline uint64 r_mideleg() { uint64 x; - asm volatile("csrr %0, mideleg" : "=r" (x) ); + asm volatile("csrr %0, mideleg" : "=r"(x)); return x; } -static inline void -w_mideleg(uint64 x) -{ - asm volatile("csrw mideleg, %0" : : "r" (x)); +static inline void w_mideleg(uint64 x) { + asm volatile("csrw mideleg, %0" : : "r"(x)); } // Supervisor Trap-Vector Base Address // low two bits are mode. -static inline void -w_stvec(uint64 x) -{ - asm volatile("csrw stvec, %0" : : "r" (x)); +static inline void w_stvec(uint64 x) { + asm volatile("csrw stvec, %0" : : "r"(x)); } -static inline uint64 -r_stvec() -{ +static inline uint64 r_stvec() { uint64 x; - asm volatile("csrr %0, stvec" : "=r" (x) ); + asm volatile("csrr %0, stvec" : "=r"(x)); return x; } // Supervisor Timer Comparison Register -static inline uint64 -r_stimecmp() -{ - uint64 x; - asm volatile("csrr %0, stimecmp" : "=r" (x) ); +__attribute__((weak)) uint64 r_stimecmp() { + uint64 x = 0; + // If not supported, return 0 return x; } -static inline void -w_stimecmp(uint64 x) -{ - asm volatile("csrw stimecmp, %0" : : "r" (x)); +__attribute__((weak)) void w_stimecmp(uint64 x) { + // If not supported, do nothing } // Machine Environment Configuration Register -static inline uint64 -r_menvcfg() -{ - uint64 x; - asm volatile("csrr %0, menvcfg" : "=r" (x) ); +__attribute__((weak)) uint64 r_menvcfg() { + uint64 x = 0; + // If not supported, return 0 return x; } -static inline void -w_menvcfg(uint64 x) -{ - asm volatile("csrw menvcfg, %0" : : "r" (x)); +__attribute__((weak)) void w_menvcfg(uint64 x) { + // If not supported, do nothing } // Physical Memory Protection -static inline void -w_pmpcfg0(uint64 x) -{ - asm volatile("csrw pmpcfg0, %0" : : "r" (x)); +static inline void w_pmpcfg0(uint64 x) { + asm volatile("csrw pmpcfg0, %0" : : "r"(x)); } -static inline void -w_pmpaddr0(uint64 x) -{ - asm volatile("csrw pmpaddr0, %0" : : "r" (x)); +static inline void w_pmpaddr0(uint64 x) { + asm volatile("csrw pmpaddr0, %0" : : "r"(x)); } // use riscv's sv39 page table scheme. @@ -224,120 +174,90 @@ w_pmpaddr0(uint64 x) // supervisor address translation and protection; // holds the address of the page table. -static inline void -w_satp(uint64 x) -{ - asm volatile("csrw satp, %0" : : "r" (x)); +static inline void w_satp(uint64 x) { + asm volatile("csrw satp, %0" : : "r"(x)); } -static inline uint64 -r_satp() -{ +static inline uint64 r_satp() { uint64 x; - asm volatile("csrr %0, satp" : "=r" (x) ); + asm volatile("csrr %0, satp" : "=r"(x)); return x; } // Supervisor Trap Cause -static inline uint64 -r_scause() -{ +static inline uint64 r_scause() { uint64 x; - asm volatile("csrr %0, scause" : "=r" (x) ); + asm volatile("csrr %0, scause" : "=r"(x)); return x; } // Supervisor Trap Value -static inline uint64 -r_stval() -{ +static inline uint64 r_stval() { uint64 x; - asm volatile("csrr %0, stval" : "=r" (x) ); + asm volatile("csrr %0, stval" : "=r"(x)); return x; } // Machine-mode Counter-Enable -static inline void -w_mcounteren(uint64 x) -{ - asm volatile("csrw mcounteren, %0" : : "r" (x)); +static inline void w_mcounteren(uint64 x) { + asm volatile("csrw mcounteren, %0" : : "r"(x)); } -static inline uint64 -r_mcounteren() -{ +static inline uint64 r_mcounteren() { uint64 x; - asm volatile("csrr %0, mcounteren" : "=r" (x) ); + asm volatile("csrr %0, mcounteren" : "=r"(x)); return x; } // machine-mode cycle counter -static inline uint64 -r_time() -{ +static inline uint64 r_time() { uint64 x; - asm volatile("csrr %0, time" : "=r" (x) ); + asm volatile("csrr %0, time" : "=r"(x)); return x; } // enable device interrupts -static inline void -intr_on() -{ +static inline void intr_on() { w_sstatus(r_sstatus() | SSTATUS_SIE); } // disable device interrupts -static inline void -intr_off() -{ +static inline void intr_off() { w_sstatus(r_sstatus() & ~SSTATUS_SIE); } // are device interrupts enabled? -static inline int -intr_get() -{ +static inline int intr_get() { uint64 x = r_sstatus(); return (x & SSTATUS_SIE) != 0; } -static inline uint64 -r_sp() -{ +static inline uint64 r_sp() { uint64 x; - asm volatile("mv %0, sp" : "=r" (x) ); + asm volatile("mv %0, sp" : "=r"(x)); return x; } // read and write tp, the thread pointer, which xv6 uses to hold // this core's hartid (core number), the index into cpus[]. -static inline uint64 -r_tp() -{ +static inline uint64 r_tp() { uint64 x; - asm volatile("mv %0, tp" : "=r" (x) ); + asm volatile("mv %0, tp" : "=r"(x)); return x; } -static inline void -w_tp(uint64 x) -{ - asm volatile("mv tp, %0" : : "r" (x)); +static inline void w_tp(uint64 x) { + asm volatile("mv tp, %0" : : "r"(x)); } -static inline uint64 -r_ra() -{ +static inline uint64 r_ra() { uint64 x; - asm volatile("mv %0, ra" : "=r" (x) ); + asm volatile("mv %0, ra" : "=r"(x)); return x; } // flush the TLB. -static inline void -sfence_vma() -{ +static inline void sfence_vma() { // the zero, zero means flush all TLB entries. asm volatile("sfence.vma zero, zero"); } @@ -361,18 +281,14 @@ typedef uint64 *pagetable_t; // 512 PTEs // shift a physical address to the right place for a PTE. #define PA2PTE(pa) ((((uint64)pa) >> 12) << 10) - #define PTE2PA(pte) (((pte) >> 10) << 12) - #define PTE_FLAGS(pte) ((pte) & 0x3FF) // extract the three 9-bit page table indices from a virtual address. -#define PXMASK 0x1FF // 9 bits -#define PXSHIFT(level) (PGSHIFT+(9*(level))) -#define PX(level, va) ((((uint64) (va)) >> PXSHIFT(level)) & PXMASK) +#define PX(level, va) ((((uint64)(va)) >> (PGSHIFT + (level)*9)) & 0x1FF) // one beyond the highest possible virtual address. // MAXVA is actually one bit less than the max allowed by // Sv39, to avoid having to sign-extend virtual addresses // that have the high bit set. -#define MAXVA (1L << (9 + 9 + 9 + 12 - 1)) +#define MAXVA (1L << (9 + 9 + 9 + 12 - 1)) \ No newline at end of file diff --git a/kernel/syscall.c b/kernel/syscall.c index ed654094cb..ea642918ef 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -101,6 +101,7 @@ extern uint64 sys_unlink(void); extern uint64 sys_link(void); extern uint64 sys_mkdir(void); extern uint64 sys_close(void); +extern uint64 sys_chmod(void); // An array mapping syscall numbers from syscall.h // to the function that handles the system call. @@ -126,6 +127,7 @@ static uint64 (*syscalls[])(void) = { [SYS_link] sys_link, [SYS_mkdir] sys_mkdir, [SYS_close] sys_close, +[SYS_chmod] sys_chmod, }; void diff --git a/kernel/syscall.h b/kernel/syscall.h index bc5f35651c..d6d1eef8ed 100644 --- a/kernel/syscall.h +++ b/kernel/syscall.h @@ -20,3 +20,4 @@ #define SYS_link 19 #define SYS_mkdir 20 #define SYS_close 21 +#define SYS_chmod 22 // Nueva syscall diff --git a/kernel/sysfile.c b/kernel/sysfile.c index 16b668cb3a..a3e7722f58 100644 --- a/kernel/sysfile.c +++ b/kernel/sysfile.c @@ -1,3 +1,4 @@ + // // File-system system calls. // Mostly argument checking, since we don't trust @@ -15,6 +16,7 @@ #include "sleeplock.h" #include "file.h" #include "fcntl.h" +#include "buf.h" // Fetch the nth word-sized system call argument as a file descriptor // and return both the descriptor and the corresponding struct file. @@ -503,3 +505,60 @@ sys_pipe(void) } return 0; } + +uint64 +sys_chmod(void) { + char path[MAXPATH]; + int mode; + struct inode *ip; + + // Validar y obtener argumentos + if (argstr(0, path, MAXPATH) < 0) { + return -1; // Error al obtener la ruta + } + + // Manejo adecuado de `argint` (sin evaluar como condición) + argint(1, &mode); + + // Verificar si el valor de mode es válido (agrega lógica de validación si es necesaria) + if (mode < 0) { + return -1; + } + printf("Path recibido: %s, Modo solicitado: %d\n", path, mode); + begin_op(); // Inicia una transacción + + ip = namei(path); // Buscar inode por ruta + if (ip == 0) { + end_op(); // Finaliza la transacción si falla + return -1; + } + + ilock(ip); + + // Leer el superblock + struct superblock sb; + readsb(ip->dev, &sb); // Asegúrate de que `readsb` esté declarada + + // Leer el inodo del buffer correspondiente + struct buf *bp = bread(ip->dev, IBLOCK(ip->inum, sb)); + struct dinode *dip = (struct dinode *)bp->data + ip->inum % IPB; + printf("Permisos actuales del archivo: %d\n", dip->perm); + + // Verificar si el archivo es inmutable + if (dip->perm == 5) { + brelse(bp); + iunlockput(ip); + end_op(); // Finaliza la transacción antes de salir + return -1; // Error: archivo inmutable + } + + dip->perm = mode; // Cambiar permisos + log_write(bp); // Sincronizar el cambio en el disco + brelse(bp); + + iunlockput(ip); + printf("Permisos cambiados exitosamente.\n"); + end_op(); // Finaliza la transacción + + return 0; +} \ No newline at end of file diff --git a/kernel/sysproc.c b/kernel/sysproc.c index 3b4d5bd863..366b47db67 100644 --- a/kernel/sysproc.c +++ b/kernel/sysproc.c @@ -21,6 +21,35 @@ sys_getpid(void) return myproc()->pid; } +uint64 +sys_getppid(void) +{ + return myproc()->parent->pid; +} + +uint64 +sys_getancestor(void) +{ + int n = 0; // Inicia n + argint(0, &n); // Obtiene el argumento de la llamada al sistema + + if (n < 0) { + return -1; // Retorna -1 si n no es valido + } + + struct proc *p = myproc(); // Obtén el proceso actual + + // Este ciclo recorre hacia atrás por la cantidad de ancestros solicitados + for (int i = 0; i < n; i++) { + if (p->parent == 0) { // Si no hay más ancestros, retorna -1 + return -1; + } + p = p->parent; // Recorre al proceso padre + } + + return p->pid; // Retorna el PID del ancestro correspondiente +} + uint64 sys_fork(void) { @@ -91,3 +120,5 @@ sys_uptime(void) release(&tickslock); return xticks; } + + diff --git a/user/chmodtest.c b/user/chmodtest.c new file mode 100644 index 0000000000..129bbe3114 --- /dev/null +++ b/user/chmodtest.c @@ -0,0 +1,46 @@ +#include "kernel/types.h" +#include "kernel/stat.h" +#include "user/user.h" +#include "kernel/fcntl.h" + +int main() { + int fd; + + // Crear un archivo + fd = open("testfile", O_CREATE | O_RDWR); + if (fd < 0) { + printf("Error: No se pudo crear el archivo\n"); + exit(1); + } + write(fd, "hola", 4); + close(fd); + + // Cambiar a solo lectura + if (chmod("testfile", 1) < 0) { + printf("Error: No se pudo cambiar a solo lectura\n"); + exit(1); + } + + // Intentar abrir en modo escritura (debe fallar) + fd = open("testfile", O_WRONLY); + if (fd >= 0) { + printf("Error: Permiso de escritura no debería estar permitido\n"); + close(fd); + exit(1); + } + + // Cambiar a inmutable + if (chmod("testfile", 5) < 0) { + printf("Error: No se pudo cambiar a inmutable\n"); + exit(1); + } + + // Intentar modificar permisos (debe fallar) + if (chmod("testfile", 3) == 0) { + printf("Error: Cambió permisos de archivo inmutable\n"); + exit(1); + } + + printf("Pruebas completadas con éxito\n"); + exit(0); +} \ No newline at end of file diff --git a/user/user.h b/user/user.h index f16fe27828..d1816f4dbf 100644 --- a/user/user.h +++ b/user/user.h @@ -19,10 +19,18 @@ int mkdir(const char*); int chdir(const char*); int dup(int); int getpid(void); +int getppid(void); +int getancestor(int); char* sbrk(int); int sleep(int); int uptime(void); +int getpriority(void); +int getboost(void); +int mprotect(void *addr, int len); +int munprotect(void *addr, int len); +int chmod(char *path, int mode); + // ulib.c int stat(const char*, struct stat*); char* strcpy(char*, const char*); @@ -40,4 +48,4 @@ void *memcpy(void *, const void *, uint); // umalloc.c void* malloc(uint); -void free(void*); +void free(void*); \ No newline at end of file diff --git a/user/usys.pl b/user/usys.pl old mode 100755 new mode 100644 index 01e426e6b3..3086079006 --- a/user/usys.pl +++ b/user/usys.pl @@ -36,3 +36,5 @@ sub entry { entry("sbrk"); entry("sleep"); entry("uptime"); +entry("chmod"); + \ No newline at end of file