← Arquitectura Cliente-Servidor

Clase 02

Mtro. Carlos Alberto Román Zamitiz · 27 ago 2026 · Tema 1 — Permisos UGO y chmod decimal, bit SetUID (chmod 4xxx), /etc/passwd, ID real vs. efectivo, Tarea 2, y fork() (retorno pid_t, PID del hijo al padre / 0 al hijo, deadlock).

Clase 2 — permisos, bit setuid, /etc/passwd y fork()
Permisos UGO y chmod (notación decimal)

Regla mnemotécnica: "ugo" (como "Hugo" sin H) → Usuario (dueño), Grupo, Otros. chmod = change mode.

  r  w  x
  4  2  1        rwx = 4+2+1 = 7      rw- = 6      r-x = 5
Bit SetUID (chmod con 4 dígitos)

Al ejecutar un binario, el proceso normalmente pertenece a quien lo ejecuta. Con el bit SetUID activo, quien lo ejecuta toma temporalmente los privilegios del dueño del archivo mientras dura la ejecución.

Se activa con un cuarto dígito a la izquierda en chmod, que indica sobre qué bloque:

4 = SetUID   (bloque de usuario)   ← el más usado
2 = SetGID   (bloque de grupo)
1 = sticky   (bloque de otros)
ej.  chmod 4511 archivo

⚠️ Riesgo de seguridad: si root pone SetUID a un ejecutable, cualquier usuario sin privilegios se vuelve root durante esa ejecución. Manejar con extrema precaución.

Usuarios en Linux · /etc/passwd · ID real vs. efectivo

cat /etc/passwd — campos separados por :

username : x : UID : GID : nombre_real : /home/... : shell
   |       |    |     |        |            |          |
 el 1º   contraseña  id    id de     GECOS (si no    dir.   tipo de
 es root  oculta   usuario  grupo    se puso, =user) home   shell

Usuarios de sistema con shell nologin: no pueden iniciar sesión interactiva (seguridad). [inaudible: la ruta se oye como "etc/al passworden"]

Tarea 2 — probar el bit SetUID

Metodología: dos terminales (una como root, otra como usuario sin privilegios). Las instrucciones de pantalla dividida en Codespaces están en la carpeta del Tema 3 del repo, aunque se usan desde el Tema 1. whoami muestra el usuario activo.

fdisk = comando solo-root para manipular la tabla de particiones (man fdisk). Sirve cualquier comando que pida privilegios. Pasos:

# 1) como usuario NO root:
fdisk -l                     # -> "permiso denegado"
                             #    (en Fedora puede solo regresar el prompt vacío)

# 2) como root, ver permisos actuales:
ls -l /sbin/fdisk            # -> 755  (rwxr-xr-x)

# 3) como root, activar SetUID:
chmod 4511 /sbin/fdisk       # -> r-s--x--x  (la 's' en vez de 'x' = SetUID activo;
                             #    el nombre se ve en rojo si hay color)

# 4) como usuario NO root otra vez:
fdisk -l                     # -> AHORA SÍ funciona: lista las particiones

# 5) OBLIGATORIO: revertir de inmediato
chmod 755 /sbin/fdisk        # (o los permisos que tuviera antes)

[inaudible: la ruta se dicta rápido como "diagonal se bin diagonal fis" → /sbin/fdisk]

Actividad 2: programa en C (programa02_ids.c en el repo) que imprime getuid() y geteuid(). Compilar gcc programa02_ids.c -o programa02_ids. Ejecutado normal → ID real == ID efectivo. Aplicando chmod 4511 al binario y ejecutándolo con otro usuario → salen distintos.

⚠️ Para sacar 10: las capturas deben mostrar ID real ≠ ID efectivo.

⚠️ No entregar la Tarea 2 todavía — el profesor no pudo hacer la demo en el laboratorio; reactivará la fecha de entrega después. (Recomienda clonar el repo localmente con git en vez de usar Codespaces.)

fork() — creación de procesos

Retorno (tipo pid_t, encapsula un entero; se imprime con %d / %i):

al PADRE  ->  el PID del hijo   (entero != 0)
al HIJO   ->  0

La variable donde guardas el retorno se duplica: en el padre vale el PID del hijo, en el hijo vale 0. Se separa el código con:

if (id_hijo != 0) {
    // código exclusivo del padre
} else {
    // código exclusivo del hijo
}

Sin if, todo lo que va después de fork() se ejecuta en ambos → sale duplicado. En programa05_fork_v1.c: la línea de antes del fork() se imprime una vez; las dos de después, dos veces cada una.

Nota semántica del profesor: antes del fork() lo llama "proceso main / principal"; "padre" solo cuando ya hay hijo.

examen⚠️ Deadlock (candado / abrazo mortal)

Si el padre espera a que termine el hijo para continuar y a la vez el hijo espera a que termine el padre → bloqueo indefinido. Única salida: Ctrl + C.

Ejemplo de ejecución — programa05_fork_v2.c

Valores de esa corrida (programa05_fork_v2.c):

DatoValor
PID del padre30405
PID del hijo30406 (el entero inmediato siguiente)
id_hijo en el padre30406
id_hijo en el hijo0
getpid() en el hijo30406
getppid() en el padrePID de la shell (bash) que lanzó el programa
getppid() en el hijo30405 (su creador es el padre)

El if puede ser != 0 (padre primero) o == 0 (hijo primero), a gusto del programador.

Para repasar (Clase 2)

Tarea moral (sin entrega): leer con calma el PDF 2 del Tema 1 (procesos).

Teoría general de procesos, ejemplos en C y los programas del profesor están en el Tema 1.