Encontré la siguiente respuesta aquí :
La respuesta corta es que el archivo .ko es su archivo de objeto vinculado con un núcleo que genera automáticamente estructuras de datos que el núcleo necesita.
El archivo .o es el archivo objeto de sus módulos, el resultado de compilar sus archivos c. El sistema de compilación del kernel crea automáticamente otro archivo C con algunas estructuras de datos que describen el módulo del kernel (llamado your_module_kmod.c), compila este archivo C en otro archivo de objeto y vincula su archivo de objeto y el archivo de objeto que creó juntos para crear el .ko archivo.
El enlazador dinámico en el kernel que se encarga de cargar los módulos del kernel, espera encontrar la estructura de datos que el kernel puso en el objeto kmod en el archivo .ko y no podrá cargar el módulo del kernel sin ellos.
También de esa fuente , citando tldp : hasta 2.4 versiones del núcleo, era ".o", y desde 2.6, es ".ko".